-
[문제해결을 위한 창의적 알고리즘] 영역 구분 (고급 p.51)알고리즘 2016. 11. 24. 12:57
이 문제는 주어진 영역을 반으로 나누어 가며 그 영역이 하얀색으로 다 채워졌는지 혹은 회색으로 다 채워졌는지 확인하는 문제이다. 해결 방법은 주어진 영역을 반으로 나눠가며, 시작 지점과 끝나는 지점 (혹은 정사각형 영역 크기)가 하나의 색으로 다 채워졌는지 확인하고 그렇지 않다면 다시 4등분하여 다시 하나의 색으로 채워졌는지 확인해 나가는 것이다.
코드에서 유의할 만한 사항은 다음과 같다.
1) 2의 배수의 배열 크기를 지정할 때 << bitwise operator를 사용할 수 있다.
2) 흰색의 개수를 세어보고 다시 회색의 개수를 세어보도록 되어 있다.
import java.util.Scanner;
public class DivideAreaSol57 {
// 데이터를 받기 위한 2차원 배열
public static int[][] P = new int[1<<7][1<<7];
public static int n;
// 하나의 색으로 다 채워졌는지 확인
public static boolean isOne(int a, int b, int s, int v) {
for (int i = a; i < a+s; i++)
for (int j = b; j < b+s; j++)
if (P[i][j]!=v)
return false;
return true;
}
// 주어진 영역이 하나의 색으로 다 채워지지 않았다면 길이를 반으로 나눠 재귀 호출
public static int f(int a, int b, int s, int v) {
if (s==1)
return P[a][b]==v?1:0;
if (isOne(a, b, s, v))
return 1;
return f(a,b,s/2,v)
+f(a+s/2,b,s/2,v)
+f(a,b+s/2,s/2,v)
+f(a+s/2,b+s/2,s/2,v);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
P[i][j]=sc.nextInt();
sc.close();
System.out.println(f(0,0,n,0));
System.out.println(f(0,0,n,1));
return;
}
}
Big O(n^2) : n은 주어진 영역의 한변 길이 (모든 값을 다 확인해 봐야 함)
https://github.com/nevermet/CreativeAlgorithmAdv/blob/master/DivideAreaSol57.java
출처: 한국정보올림피아드(2001 전국본선 중등부)
'알고리즘' 카테고리의 다른 글
[문제해결을 위한 창의적 알고리즘] 고급편 목록 (0) 2016.12.03 [문제해결을 위한 창의적 알고리즘] 이진 암호화 (고급 p.58) (0) 2016.12.03 [문제해결을 위한 창의적 알고리즘] Distance of Nodes (고급, p47) (0) 2016.09.16 [문제해결을 위한 창의적 알고리즘] 타일 채우기 (고급, p35) (0) 2016.09.16 [문제해결을 위한 창의적 알고리즘] Combination (고급, p29) (0) 2016.09.16