풀이방법
사용된 것:
분할 정복
재귀
2022.05.18
분할 정복 문제이고, 재귀적으로 정의된 함수를 사용한다.
사용한 전역변수는 다음과 같이 3개이다.
- boolean[][] paper : 종이 정보. 파란색인 부분은 true, 하얀색인 부분은 false로 저장한다.
- int answer_w : 첫 줄에 출력될 정답. 완성된 하얀 색종이의 개수를 저장한다.
- int answer_b : 둘째 줄에 출력될 정답. 완성된 파란 색종이의 개수를 저장한다.
먼저 종이 정보를 읽어오고,
answer_w와 answer_b를 0으로 초기화시키고,
함수 cut()을 수행하고,
answer_w와 answer_b를 출력하면 된다.
cut()의 구성은 다음과 같다.
함수 cut()
개요
cut()은 주어진 영역의 색이 통일되어있는지를 점검하여,
통일되어있다면 answer_w 또는 answer_h 중 하나를 1 증가시키고
통일되어있지 않다면 영역을 4개로 쪼개어 이 4개 부분 영역에 대하여 재귀적으로 cut()을 실행하는 함수이다.
매개변수
- int startrow : cut()에서 점검할 영역의 시작부분(가장 왼쪽 위 지점)의 열 좌표
- int startcol : cut()에서 점검할 영역의 시작부분(가장 왼쪽 위 지점)의 행 좌표
- int len : cut()에서 점검할 영역의 한 변의 길이
작동방식
주어진 영역의 첫 칸(가장 왼쪽 위 지점)의 색을 boolean형 변수 first에 저장한다.
주어진 영역의 전체가 first와 색이 같은지 점검한다. 그 점검법은 다음과 같다.
- boolean형 변수 check를 선언하고 true로 초기화한다.
- 2중 for문을 사용하여 영역의 모든 칸을 점검한다. 그러다가 first와 색이 다른 칸이 발견되는 순간! check를 false로 바꾸고 2중 for문을 종료한다. first와 색이 다른 칸이 하나도 없다면 2중 for문은 중단되지 않은 채 끝나고 check는 true로 남아있게 된다.
check가 false라면,
영역을 4개로 쪼갠 후 그 4개의 영역에 대하여 재귀적으로 cut을 수행한다.
check가 true라면,
first가 true일 경우 answer_b의 값을 1 증가시킨다.
first가 false일 경우 answer_w의 값을 1 증가시킨다.
코드
Java(2022.05.18)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static boolean[][] paper; //종이
static int answer_w; //하얀 색종이의 개수
static int answer_b; //파란 색종이의 개수
//특정 영역을 점검하여, 한 색상으로 통일되어있지 않으면 자르는 함수
public static void cut(int startrow, int startcol, int len) {
//startrow와 startcol는 영역의 가장 왼쪽 위 부분의 좌표
//len은 영역의 한 변의 길이
boolean first = paper[startrow][startcol]; //가장 왼쪽 위 부분의 색
boolean check = true; //점검결과가 저장될 boolean 변수
//영역의 모든 부분이 first와 동일한지 점검
for(int i = startrow; i<startrow+len; i++) {
for(int j = startcol; j<startcol+len; j++) {
if(paper[i][j]!=first) {check = false; break;}
}
}
//색이 통일되어있지 않다면 자르기
if(!check) {
//네 부분의 시작위치 지정
int[] r = {0, 0, len/2, len/2};
int[] c = {0, len/2, 0, len/2};
//네 부분에 대하여 재귀적으로 cut 수행
for(int i = 0; i<4; i++) {
cut(startrow+r[i], startcol+c[i], len/2);
}
}
//색이 통일되어있다면 정답에 반영하기
else {
if(first) answer_b++;
else answer_w++;
}
return;
}
public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//입력값 읽어오기
int n = Integer.parseInt(br.readLine());
paper = new boolean[n][n];
for(int i = 0; i<n; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
for(int j= 0; j<n; j++) {
if(st.nextToken().equals("1")) paper[i][j]=true;
else paper[i][j] = false;
}
}
//변수 초기화
answer_w = 0;
answer_b = 0;
//자르기
cut(0, 0, n);
//정답 출력
System.out.println(answer_w);
System.out.println(answer_b);
}
}
'알고리즘 문제풀이 > 백준' 카테고리의 다른 글
#3009 : 네 번째 점 (0) | 2022.05.20 |
---|---|
#2447 : 별 찍기 - 10 (0) | 2022.05.18 |
#1269 : 대칭 차집합 (0) | 2022.05.16 |
#2851 : 슈퍼 마리오 (0) | 2022.05.12 |
#9742 : 순열 (0) | 2022.05.10 |