알고리즘/백준[문제풀이]
백준[자바]_1992_쿼드트리_분할정복
Leo.K
2022. 6. 14. 10:54
728x90
오늘은 색종이 문제에 이어서 두 번째로 분할정복의 문제를 풀이했다. 이번 문제는 쿼드트리를 생각해보는 문제로 트리의 개념이 직접적으로 코드에 구현되지는 않지만, 한 번쯤 생각해볼만한 문제이다.
우리가 평소에 알고 있던 트리는 이진트리로서 한 노드가 가질 수 있는 자식노드가 최대 2개인 트리의 구조이다. 그렇다면 쿼드 트리는 무엇일까? 말 그대로 한 노드가 가질 수 있는 자식 노드가 최대 4개인 트리의 구조이다. 그림상으로 보면 다음과 같다.
그렇다면 이 문제에서 쿼드트리를 어떻게 적용해볼수 있을까? 문제에서 주어지는 조건을 한 번 생각해보자
[ 문제 접근 & 알고리즘 ]
- 0과 1로만 구성된 흑백영상이 모두 0이면 괄호없이 0, 모두 1이면 괄호없이 1을 출력한다.
- 이때, 흑백영상을 자르는 기준을 왼쪽위, 오른쪽위, 왼쪽아래, 오른쪽아래 4개를 기준으로 해당 영역을 하나의 문자로 압축할 수 있는지 없는지 여부를 판단해야 한다.
- 왼쪽 위를 현재 위치로 잡는다면, 나머지 세 영역의 범위는 기준이 되는 현재 위치로 부터 분할한 영역의 크기만큼, x와 y좌표를 이동하면서 잡는다.
- 문제에서 주어진 예제로 간단히 설명하면, 시작위치가 0,0이고 크기가 8인경우
- 가장 먼저, 재귀를 시작할 때 모든 값이 0 또는 1로 구성되어 있는지 확인하고 아니라면 크기를 반으로 줄인다.
- 현재위치 0,0을 기준으로 크기의 반(8/2=4)만큼 x와 y값을 이동시킨다.
- 그렇다면 (시작위치x,y,크기)라고 표현했을 때, (0,0,4), (4,0,4), (0,4,4), (4,4,4)이렇게 네 가지의 경우의 수를 구할 수 있는데, 각 경우의 수에서 좌표값을 시작위치로 잡고 2의 검사 과정을 거쳐서 압축할 수 있다면 압축하고, 불가능하다면, 3~4의 과정을 반복하면서 하나의 영역에 대하여 4가지 경우의 수(쿼드 트리)로 분할하여 압축할 수 있는지(정복)를 확인해보면 된다.
- 이때 나누어지는 4가지 경우의 수로 재귀를 호출하면 되는 것이고, 주의할 점은 재귀를 호출하기 전에 괄호를 열고, 재귀가 끝나는 지점에서 괄호를 닫아주면 된다.
간단한 예를 도식화 하면 아래와 같다.
[ 소스 코드 ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
package DivideAndConquor;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class _1992_쿼드트리 {
static int n;
static int map[][];
static StringBuilder sb = new StringBuilder();
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(br.readLine());
map = new int[n][n];
for(int i=0; i<n; i++) {
String str = br.readLine();
for(int j=0; j<n;j++) {
map[i][j] = str.charAt(j)-'0';
}
}
dfs(0,0,n);
System.out.println(sb);
}
private static void dfs(int x, int y, int size) {
// TODO Auto-generated method stub
if(isCompress(x,y,size)) {
sb.append(map[x][y]);
return;
}
int step = size/2;
sb.append('(');
dfs(x,y, step); //왼쪽 위 : 현재위치
dfs(x,y+step, step); //오른쪽 위 :
dfs(x+step,y, step); //왼쪽 아래 :
dfs(x+step,y+step, step); //오른쪽 아래 :
sb.append(')');
}
//압축 가능 여부
private static boolean isCompress(int x, int y, int size) {
// TODO Auto-generated method stub
int val = map[x][y];
//시작값과 비교해서 다르면 불가능
for(int i=x; i<x+size; i++) {
for(int j=y; j<y+size; j++) {
if(val != map[i][j]) {
return false;
}
}
}
//모두 같으면 압축 가능
return true;
}
}
|
cs |
728x90