본문 바로가기
PS 문제 풀이/Baekjoon

[BOJ] 백준 17136 색종이 붙이기

by 까망 하르방 2021. 2. 22.
반응형

출처: https://www.acmicpc.net/problem/17136

 Input 

1 1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1 1

1 1 1 1 0 0 1 1 1 1

1 1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 0 0 0 0

 

 Output 

9

5가지 종류의 색종이로 10 x 10 종이 위에 1 을 색종이 최소 개수로 덮는 문제입니다.

※ 색종이 종류: 1×1, 2×2, 3×3, 4×4, 5×5

- 『 0 』인 부분을 덮어서는 안됩니다.

- 색종이가 겹쳐서는 안됩니다. 

Greedy 방식으로 큰 색종이 작은 색종이까지 가능한 순서대로 구현했지만 

아래 Case에서 처리가 안되어 Brute Force 방식으로 구현

 

구현 순서

① Board 배열을 순회하며, 『 1 』 탐색

② 『 1 』을 발견하였을 경우, 작은 크기(1x1) 부터 큰 크기(5x5) 재귀 탐색

③ Board 배열에 모든 『 1 』 덮였을 때, 사용된 색종이 개수가 가장 적은 경우 도출 


import java.util.Scanner;

public class Main {

    static int paper[] = { 0, 5, 5, 5, 5, 5 };
    static int board[][];
    static int answer = Integer.MAX_VALUE;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        board = new int[11][11];

        // 『1』의 개수
        int num_of_1 = 0;
        for (int i = 1; i <= 10; i++) {
            for (int j = 1; j <= 10; j++) {
                board[i][j] = Integer.parseInt(sc.next());
                if (board[i][j] == 1) num_of_1++;
            }
        } // end of input


        // 처음 주어진 배열에서
        if (num_of_1 == 0) {
            System.out.println(0);
            return;
        }
        
        // 1행부터 영역을 살펴본다.
        solve(1);
        
        if(answer == Integer.MAX_VALUE) System.out.println(-1);
        else System.out.println(answer);
    }

    private static void solve(int x) {
        for (int r = x; r <= 10; r++) {
            for (int c = 1; c <= 10; c++) {

                // 처리할 『1』 탐색
                if (board[r][c] == 1) {
                    // 해당 영역에 가능한 색종이가 있는지 확인
                    for (int paperSize=1; paperSize<=5; paperSize++) {
                        // 색종이가 남아 있는지 확인
                        if (paper[paperSize] > 0) {
                            // 지정된 색종이 크기 영역이 모두 『1』인지 확인
                            if (checkArea(r, c, paperSize)) {
                                // 해당영역의 숫자를 『1』 → 『0』으로 전환
                                for (int i = r; i < r + paperSize; i++) {
                                    for (int j = c; j < c + paperSize; j++) {
                                        board[i][j] = 0;
                                    }
                                }
                                // 색종이 사용
                                paper[paperSize]--;
                                
                                // 재귀탐색
                                solve(r);

                                // 해당영역의 숫자를 다시 환복 『0』 → 『1』
                                for (int i = r; i < r + paperSize; i++) {
                                    for (int j = c; j < c + paperSize; j++) {
                                        board[i][j] = 1;
                                    }
                                }
                                // 사용했던  색종이 반환
                                paper[paperSize]++;
                            }
                        }
                    }

                    // 1~5번 어떤 종이로도 붙이지 못했다면
                    // 여전히 『1』로 남았을 경우
                    if (board[r][c] == 1) return;
                }
            }
        }
        
        // 모든 영역이 0이 되었으므로,
        // 사용된 색종이 개수 확인
        int paperCnt = 25;
        for (int i = 1; i <= 5; i++) {
            paperCnt -= paper[i];
        }

        answer = answer > paperCnt ? paperCnt : answer;
    }


    private static boolean checkArea(int r, int c, int paperSize) {
        // 범위를 벗어나면
        if(r < 1 || c < 1 || r + paperSize > 11|| c + paperSize > 11) return false;
        
        // 해당 영역이 모두 1인지 확인
        for (int i = r; i < r + paperSize; i++) {
            for (int j = c; j < c + paperSize; j++) {
                if (board[i][j] != 1) {
                    return false;
                }
            }
        }
        return true;
    }
}

 

반응형

'PS 문제 풀이 > Baekjoon' 카테고리의 다른 글

[BOJ] 백준 1764 듣보잡  (0) 2021.02.22
[BOJ] 백준 17070 파이프 옮기기 1  (0) 2021.02.22
[BOJ] 백준 10814 나이순 정렬  (0) 2021.02.22
[BOJ] 백준 1708 블록 껍질  (0) 2021.02.22
[BOJ] 백준 17135 캐슬 디펜스  (0) 2021.02.22

댓글