Coding Test

[백준] 2630번 색종이 만들기 자바 (분할정복)

연_우리 2022. 2. 22. 15:22
반응형

목차

     

     

     

    https://www.acmicpc.net/problem/2630

     

    2630번: 색종이 만들기

    첫째 줄에는 전체 종이의 한 변의 길이 N이 주어져 있다. N은 2, 4, 8, 16, 32, 64, 128 중 하나이다. 색종이의 각 가로줄의 정사각형칸들의 색이 윗줄부터 차례로 둘째 줄부터 마지막 줄까지 주어진다.

    www.acmicpc.net

     

     

     

     

    문제풀이

    분할정복은 재귀함수를 사용하여

    문제를 해결할 수 있을 때까지 하위문제로 나누어 문제를 해결하고, 결과를 다시 전체에 합치는 방법이다.

     

     

    1번째는 모든 좌표를 대상으로 2중 for문을 돌려 색을 판단한다.

     => 모두 같다면 색깔에 맞게 저장

     => 하나라도 다른 색깔이 있다면 4분할

          좌측상단 : x는 0~4까지, y는 0~4까지 탐색

          좌측하단 : x는 0~4까지, y는 4~8까지 탐색

          우측상단 : x는 4~8까지, y는 0~4까지 탐색

          우측하단 : x는 4~8까지, y는 4~8까지 탐색

     

    2번째는 x는 0~4까지, y는 0~4까지를 대상으로 2중 for문을 돌려 색을 판단한다.

     => 모두 같다면 색깔에 맞게 저장

     => 하나라도 다른 색깔이 있다면 4분할 ... 반복

     

     

    탐색범위만 바뀔 뿐 색을 판단하는 기능은 같기때문에 colorCheck 메서드를 생성한다.

     

    colorCheck메서드를 실행하여 색이 모두 같다면 white와 blue를 +1만큼 증가해야한다.

    colorCheck메서드를 실행하여 색이 다르다면 좌표를 4개로 나누어야한다.

     => 색이 다르다면 반복적으로 좌표범위를 나누고

          나뉘어진 좌표범위에서 색이 같아지면, white와 blue의 개수를 전체적으로 합쳐야한다.

          따라서 재귀함수로 구현한다.

     

     

    그림으로 보는 풀이

    왼쪽에서 오른쪽으로 한줄씩 읽으면된다..!

    colorCheck의 for-row, for-col은 주어진 x와 y의 범위를 나타낸다.

     

     

     

     

    제출코드

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.StringTokenizer;
    
    public class Main {
    
        static int white = 0;
        static int blue = 0;
        static int[][] board;
    
        public static void main(String[] args) throws IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            int N = Integer.parseInt(br.readLine());
            StringTokenizer st;
    
            board = new int[N][N];
            for (int i = 0; i < N; i++) {
                st = new StringTokenizer(br.readLine(), " ");
                for (int j = 0; j < N; j++) {
                     int num = Integer.parseInt(st.nextToken());
                     board[i][j] = num;
                }
            }
            //===============================
            //입력값 저장
    
            partition(0, 0, N);
            //색상 판단할 시작점입력
            System.out.println(white);
            System.out.println(blue);
        }
    
        private static void partition(int row, int col, int size) {
            //색상 모두 같은지 확인. 
            if(colorCheck(row, col, size)){	
                //색상이 모두 같다면 실행
                if(board[row][col] == 0){	
                    white++;
                }else{
                    blue++;
                }
                return;
            }
    
            //색상이 모두 같지 않다면 분할
            int newSize = size / 2;
            partition(row, col, newSize);                   //좌측상단
            partition(row, col+newSize, newSize);           //좌측하단
            partition(row+newSize, col, newSize);           //우측상단
            partition(row+newSize, col+newSize, newSize); 	//우측하단
        }
    
        private static boolean colorCheck(int row, int col, int size) {
            int color = board[row][col];	// 기준 Color
    
            for(int i = row; i < row + size; i++) {
                for(int j = col; j < col + size; j++) {
                    // 색상 같지않으면 false
                    if(board[i][j] != color) {
                        return false;
                    }
                }
            }
            // 색상 모두 같으면 true
            return true;
        }
    
    }

     

     

     

     

    반응형
    • 네이버 블러그 공유하기
    • 페이스북 공유하기
    • 트위터 공유하기
    • 구글 플러스 공유하기
    • 카카오톡 공유하기