문제 링크
주의사항
- JAVA를 사용하여 프로그램을 사용하였습니다.
- 백준에서 코드를 작성하였을 때 아래 형태에서 Main에서 결과가 출력되어야 합니다.
public class Main{
public static void main(String[] args){
}
}
문제 설명
접근 방법
분할 정복 알고리즘은 일정한 간격으로 입력된 값을 분할하여 조건에 맞는지 확인하고 틀리면 다시 일정한 간격으로 분할하는 것을 반복하여 조건에 만족할 때까지 진행하는 알고리즘입니다.
조건에 맞는지 확인하고 일정한 간격으로 나눌 수 있도록 재귀를 사용하여 구현할 것입니다.
문제를 살펴보면 종이를 적절한 크기로 자른다는 내용을 살펴보면 분할한다는 내용과 동일합니다.
해결 알고리즘을 살펴보면
1. 처음 종이가 모두가 동일한 숫자 1/0/-1으로 이루어지는지 확인합니다.
2. 하나의 숫자로 이루어지지 못한다면 9분할로 나눕니다.
3. 9분할로 나뉜 종이마다 모두 동일한 숫자 1/0/-1으로 이루어지는지 확인합니다.
4. 위 과정을 반복하여 1/0/-1이 구분되는 종이의 개수를 차례대로 출력합니다.
예제 입력을 살펴보면
1. 첫 종이가 모두가 동일한 숫자 1/0/-1으로 이루어지는지 확인합니다.
따로 표를 작성하지 않아도 1/0/-1이 섞여있으므로 하나의 종이가 아닙니다.
2. 9분할하여 분할된 종이들이 모두가 동일한 숫자 1/0/-1으로 이루어지는지 확인합니다.
※(6, 0)을 기준으로 분할된 화면만 표로 작성하여 알고리즘이 어떻게 굴러가는지 알려드리겠습니다.
9분할로 나누었지만 모두가 동일한 숫자 1/0/-1이 아니기 때문에 종이가 아닙니다.
0 | 1 | -1 |
0 | -1 | 1 |
0 | 1 | -1 |
3. 9분할로 나누었던 종이를 다시 9분할로 나눕니다.
9분할을 나누면 크기가 모두 1이기 때문에 자신의 숫자가 그에 해당하는 종이가 됩니다.
그래서 1 = 3개, 0 = 3개, -1 = 3개가 됩니다.
- BufferedReader를 사용하여 입력 값을 받았습니다.
- StringTokenizer를 사용하여 띄어쓰기 기준으로 입력값을 나누어 배열에 저장하였습니다.
- 종이 개수/종이 확인/종이 개수 더하기을 수행하는 paperCount/paperCheck/countPlus 함수를 만들었습니다.
- 함수를 실행 후 BufferedWriter에 종이의 개수를 저장하였습니다.
- BufferedWriter에 저장된 결과값을 출력하였습니다.
- paperCount함수는 위 알고리즘을 재귀를 통해 구현하였으며 화면의 최소크기(1)이 되었을 때는 종이에 숫자에 따라 그대로 개수를 더하였습니다.
- paperCheck는 2중 for문을 사용하여 분할된 화면이 모두 1/0/-1인지 확인하였습니다.
- countPlus는 종이에 적인 숫자에 따라 개수를 더하여주도록 하였습니다.
결과 코드
import java.io.*;
import java.util.*;
public class Main{
static int[][] paper; //종이 값 저장 배열
static int minus = 0, zero = 0, plus = 0; // 1,0,-1 종이 개수 변수
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//입력값 처리하는 BufferedReader
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
//결과값 출력하는 BufferedWriter
//----------입력 값 저장 및 배열 초기화----------
StringTokenizer st;
int size = Integer.parseInt(br.readLine());
paper = new int[size][size];
for(int i=0;i<size;i++) {
st = new StringTokenizer(br.readLine()," ");
for(int j=0;j<size;j++)
paper[i][j] = Integer.parseInt(st.nextToken());
}
paperCount(0, 0, size); //함수 실행
bw.write(minus + "\n" + zero + "\n" + plus + "\n"); //결과 저장
bw.flush(); //결과 출력
bw.close();
br.close();
}
//--------종이 개수 구하는 함수----------
public static void paperCount(int start, int end, int size) {
if(size == 1) { //크기가 1일 때
countPlus(paper[start][end]);
return;
}
if(paperCheck(start, end, size)) //모두 1,0,-1로 이루어질 때
countPlus(paper[start][end]);
else {
//---------9분할 진행-------------
int tempSize = size/3;
paperCount(start, end, tempSize);
paperCount(start, end + tempSize, tempSize);
paperCount(start, end + (tempSize*2), tempSize);
paperCount(start + tempSize, end, tempSize);
paperCount(start + tempSize, end + tempSize, tempSize);
paperCount(start + tempSize, end + (tempSize*2), tempSize);
paperCount(start + (tempSize*2), end, tempSize);
paperCount(start + (tempSize*2), end + tempSize, tempSize);
paperCount(start + (tempSize*2), end + (tempSize*2), tempSize);
}
}
//-------종이가 모두 동일한 1,0,-1으로 되어있는지 확인하는 함수----------
public static boolean paperCheck(int start, int end, int size) {
int firstValue = paper[start][end];
int start_end = start + size;
int end_end = end + size;
for(int i=start;i<start_end;i++) {
for(int j=end;j<end_end;j++) {
if(paper[i][j]!=firstValue)
return false;
}
}
return true;
}
//---------종이 개수 더하는함수----------
public static void countPlus(int n) {
if(n==-1)
minus++;
else if(n==0)
zero++;
else
plus++;
}
}
'백준' 카테고리의 다른 글
[백준] 단계별로 풀어보기(단계:20,분할 정복,JAVA)11401번, 이항 계수 3 (0) | 2022.02.20 |
---|---|
[백준] 단계별로 풀어보기(단계:20,분할 정복,JAVA)1629번, 곱셈 (0) | 2022.02.18 |
[백준] 단계별로 풀어보기(단계:20,분할 정복,JAVA)1992번, 쿼드트리 (0) | 2022.02.17 |
[백준] 단계별로 풀어보기(단계:20,분할 정복,JAVA)2630번, 색종이 만들기 (0) | 2022.02.17 |
[백준] 단계별로 풀어보기(단계:19,큐/덱,JAVA)5430번, AC (0) | 2022.02.16 |
댓글