1 분 소요

key word : 재귀, 쿼드 트리, 분할 정복

문제

색종이가 같은 색으로 칠해져있는지 확인한 후, 그렇지 않다면 색종이를 4분할 해가면서 같은 색으로만 칠해져있는 경우를 찾는다. 그 후 각 색깔의 종이가 몇 개인지 세는 문제이다.

아이디어

전체를 돌면서 같은 색인지 확인한 뒤, 아니라면 종이를 사분할해서 같은 작업을 반복하면 되는 쉬운 문제이다.

재귀로 풀 수 있으며 재귀 함수 내의 로직이 매우 간단하여 분할해서 넘겨주는 작업만 잘 하면 될 것 같았다. 그나마 주의할 점이라면 for문 내의 i의 값을 시작하는 배열의 위치로 초기화하고, 초기화값 + 돌아야하는 범위까지만 돌게끔 해줘야한다는 점이다. 습관적으로 i = 0 으로 썼다가 고쳤다.

아이디어 자체가 단순하므로 바로 구현에 들어갔다.



구현

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.StringTokenizer;

public class ColorPaper {
	static int N;
	static int[][] paper;
	static int blue = 0, white = 0;

	public static void init() throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		N = Integer.parseInt(br.readLine());

		paper = new int[N][N];

		for(int i=0; i<N; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			for(int j=0; j<N; j++) {
				paper[i][j] = Integer.parseInt(st.nextToken());
			}
		}
	}

	public static void recursion(int n, int r, int c) {
		if(n == 1) {
			if(paper[r][c] == 1) {
				blue++;
			}else {
				white++;
			}
			return;
		}

		int color = paper[r][c];
		for(int i=r; i<r + n; i++) {
			for(int j=c; j<c + n; j++) {
				if(paper[i][j] != color) {
					int half = n / 2;
					recursion(half, r, c);
					recursion(half, r, c + half);
					recursion(half, r + half, c);
					recursion(half, r + half, c + half);
					return;
				}
			}
		}
		if(color == 1) {
			blue++;
		}else {
			white++;
		}
	}

	public static void main(String[] args) throws IOException{
		init();
		recursion(N, 0, 0);
		System.out.println(white);
		System.out.println(blue);
	}

}

업데이트: