문제를 풀면서 한창 고민을 했던 문제이고 내가 약한 재귀 함수 문제를 좀더 연습할수있는 문제여서 정리할겸 글을 작성합니다.
문제 설명
전체 종이의 크기가 N×N(N=2k, k는 1 이상 7 이하의 자연수) 이라면 종이를 자르는 규칙은 다음과 같다.
전체 종이가 모두 같은 색으로 칠해져 있지 않으면 가로와 세로로 중간 부분을 잘라서 <그림 2>의 I, II, III, IV와 같이 똑같은 크기의 네 개의 N/2 × N/2색종이로 나눈다. 나누어진 종이 I, II, III, IV 각각에 대해서도 앞에서와 마찬가지로 모두 같은 색으로 칠해져 있지 않으면 같은 방법으로 똑같은 크기의 네 개의 색종이로 나눈다. 이와 같은 과정을 잘라진 종이가 모두 하얀색 또는 모두 파란색으로 칠해져 있거나, 하나의 정사각형 칸이 되어 더 이상 자를 수 없을 때까지 반복한다.
위와 같은 규칙에 따라 잘랐을 때 <그림 3>은 <그림 1>의 종이를 처음 나눈 후의 상태를, <그림 4>는 두 번째 나눈 후의 상태를, <그림 5>는 최종적으로 만들어진 다양한 크기의 9장의 하얀색 색종이와 7장의 파란색 색종이를 보여주고 있다.
입력으로 주어진 종이의 한 변의 길이 N과 각 정사각형칸의 색(하얀색 또는 파란색)이 주어질 때 잘라진 하얀색 색종이와 파란색 색종이의 개수를 구하는 프로그램을 작성하시오.
해당 문제를 풀수있는 방법을 생각을 해보았고 재귀를 써야 한다고 생각은 했지만 이 문제에 어떻게 사용해야하는지는 생각나는 방법이 없었다. 결국 블로그에 검색해서 푸는방법을 검색 해보았다. 역시 풀이 방법까지 자세하게 설명이 되어있었고 참고해서 문제를 풀었다.
범위 안에 있는 컬러가 맞지 않을경우 4분할로 쪼개서 다시 시작과 끝을 정의하여 4분할이 컬러가 모두 맞을때까지 재귀를 돌린다
이생각을 기준으로 해서 문제를 풀었고 의외로 쉽게 풀렸다.
int color = paper[x][y];
for (int i = x; i < x+N; i++) {
for (int j = y; j < y+N; j++) {
if(color != paper[i][j]) {
solution(x,y,N/2);
solution(x,y+N/2,N/2);
solution(x+N/2,y,N/2);
solution(x+N/2,y+N/2,N/2);
return;
}
}
}
if(color == 0) {
list.add(0);
} else {
list.add(1);
}
[전체 풀이 코드]
import java.io.*;
import java.util.*;
class Main {
static BufferedReader br;
static StringBuilder sb;
static int[][] paper;
static int n;
static List<Integer> list;
// input
static void input () {
try {
// 라이브
br = new BufferedReader(new InputStreamReader(System.in));
sb = new StringBuilder();
n = Integer.parseInt(br.readLine());
paper = new int[n][n];
list = new ArrayList<>();
StringTokenizer st;
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine()," ");
for (int j = 0; j < n; j++) {
paper[i][j] = Integer.parseInt(st.nextToken());
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
//main
public static void main(String[] args) throws IOException {
input();
solution(0,0,n);
int zero = 0;
int one = 0;
for (int i = 0; i < list.size(); i++) {
if(list.get(i) == 0) {
zero += 1;
} else {
one += 1;
}
}
System.out.println(zero);
System.out.println(one);
}
static void solution (int x,int y,int N) {
int color = paper[x][y];
for (int i = x; i < x+N; i++) {
for (int j = y; j < y+N; j++) {
if(color != paper[i][j]) {
solution(x,y,N/2);
solution(x,y+N/2,N/2);
solution(x+N/2,y,N/2);
solution(x+N/2,y+N/2,N/2);
return;
}
}
}
if(color == 0) {
list.add(0);
} else {
list.add(1);
}
}
}
여기서 조금의 코드를 추가하면 풀수있는 문제도 있으니 한번 풀어보는걸 권장드립니다.
https://www.acmicpc.net/problem/1992
'알고리즘 > 백준' 카테고리의 다른 글
[BoJ] - 1043번 거짓말 (2) | 2023.12.12 |
---|---|
[BoJ] - 1015번 수열 정렬 (0) | 2023.10.22 |
정수 삼각형 - 파이썬 (DP) (0) | 2022.05.15 |
병사 배치하기 - DP(파이썬) - 이코테 문제 (0) | 2022.05.08 |
K 번째수 - 파이썬 (이분탐색) (0) | 2022.05.07 |