코드 저장소

공부에는 끝이 없다!

JAVA/코딩 테스트

백준 문제 풀이 - 2차원 배열 단계 - 2563번 색종이 (실버 5)

VarcharC2K 2023. 8. 23. 15:03

해당 문제는 총 100x100의 크기의 도화지에 색종이를 붙인다고 할때, 색종이가 붙어 있는 영역의 전체 넓이를 구하는 문제이다.

색종이의 수는 처음에 입력되며 크기는 10x10으로 고정이지만, 겹치는 부분이 생길 수 있으므로, 그것을 감안하여 계산하여야 한다.

 

나는 전체 도화지를 100x100의 빈 2차원 배열을 만들어 두고, 2차원 배열 안에 색종이의 시작점이 주어지면 시작점에서 + 10으로 2중 for문을 돌려서 해당하는 인덱스에 집어넣은 후, 값이 있는 것만 다른 배열에 담아 해당 배열의 크기를 구하여 계산하는 방식으로 설계를 하였다.

 

코드는 다음과 같다.

import java.io.*;
import java.nio.Buffer;
import java.util.*;

class Main{
    public static int[][] page;
    public static int n,width,height;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        page = new int[100][100];
        StringTokenizer st;
        ArrayList<Integer> arr = new ArrayList<>();

        n = Integer.parseInt(br.readLine());
        for(int i = 0; i < n; i++){
            st = new StringTokenizer(br.readLine());
            width = Integer.parseInt(st.nextToken());
            height = Integer.parseInt(st.nextToken());

            for(int j = width; j < width+10; j++){
                for(int k = height; k < height+10; k++){
                    page[j][k] = 1;
                }
            }
        }

        br.close();
        for(int i = 0; i < 100; i++){
            for(int j = 0; j < 100; j++){
                if(page[i][j] == 1){
                    arr.add(1);
                }
            }
        }

        System.out.println(arr.size());
    }
}

코드를 보면 알겠지만 처음에 색종이의 수량을 변수에 담아 저장한다.

그 후, 색종이의 수만큼 반복하며 색종이의 시작 위치를 입력받는데, 이를 width와 height 변수에 담는다.

그 후, width와 height의 + 10만큼 반복하며 page의 해당 인덱스에 넣은 후, 2중 반복문을 통하여 ArrayList arr에 값이 있는 경우에만 담는다. 

마지막으로 arr의 size를 출력하면 완료이다.

 

보면 알겠지만 여러번 반복하는 만큼 그다지 효율적인 구조는 아닌데, 어떻게 바꾸면 좋을까 다른 사람들의 풀이를 보다가 개인적으론 효율적이라고 생각하는 방법을 찾았다.

import java.io.*;
import java.util.*;

public class Main {

	    public static void main(String[] args) throws IOException {
	        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	        int total = 0;  //검은 영역의 넓이
	        int n = Integer.parseInt(br.readLine());  //색종이 개수
	        boolean[][] arr = new boolean[101][101];  //도화지
	        for (int i = 0; i < n; i++) {
	            StringTokenizer st = new StringTokenizer(br.readLine());
	            int x = Integer.parseInt(st.nextToken());
	            int y = Integer.parseInt(st.nextToken());
	            //(x,y)부터 (x+9, y+9)까지의 영역을 하나씩 체크한 후 총 넓이에 더해준다
	            for (int j = x; j < x+10; j++) {
	                for (int k = y; k < y+10; k++) {
	                    if (!arr[j][k]) {
	                        arr[j][k] = true;
	                        total++;
	                    }
	                }
	            }
	        }
	        System.out.print(total);
	    }
	}

우선 빈 boolean 타입의 2차배열을 만들어준다.

그리고 똑같이 색종이의 수만큼 반복하며 시작에서 부터 색종이의 크기만큼 2중 for문을 이용하여 넣는데, 여기서 눈여겨 볼 점은, 넣는것과 동시에 배열에 값이 있나 없나를 확인하고 total이라는 결과값을 따로 정하여 크기를 카운트 하는 것이다.

 

내가 2중 포문을 2번 사용한 것은 결국 값이 들어있는 배열의 크기를 얻기 위하여 값이 있는 것만 다른 배열에 복사한 것이였는데, 위의 코드를 보니 굳이 그럴 필요없이 입력단계에서 바로 답을 구할 수 있다는 것을 알 수 있었다.

입력시에 출력 값을 동시에 확인 할 수 있었던 만큼, 입력을 위한 로직과 출력을 위한 로직을 구분 할 필요가 없었는데 해당 작업을 따로 분리하면서 불필요한 로직이 추가 되었던 것 같다.

 

코드를 짜면서 아무래도 각 로직별로 분리하는 습관이 들어있다 보니, 별 생각 없이 출력 로직을 따로 분리하였는데, 효율면이나 기독성 면을 보았을 때, 필요없는 경우 굳이 그렇게 나누지 않아도 된다는 것을 알 수 있었다.