본문 바로가기

ProgramSoliving

백준 : 17136

반응형

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

 

17136번: 색종이 붙이기

<그림 1>과 같이 정사각형 모양을 한 다섯 종류의 색종이가 있다. 색종이의 크기는 1×1, 2×2, 3×3, 4×4, 5×5로 총 다섯 종류가 있으며, 각 종류의 색종이는 5개씩 가지고 있다. <그림 1> 색종이를 크기가 10×10인 종이 위에 붙이려고 한다. 종이는 1×1 크기의 칸으로 나누어져 있으며, 각각의 칸에는 0 또는 1이 적혀 있다. 1이 적힌 칸은 모두 색종이로 덮여져야 한다. 색종이를 붙일 때는 종이의 경계 밖으로 나가서는 안되고, 겹쳐

www.acmicpc.net

생각해보기

처음 단순 완전탐색을 생각햇을때 실수햇던점은 처음 1이 나온시점에서 DFS가 실패하면 그다음 칸으로가서 DFS를 실행한다. 이럴 경우 1이라는 숫자를 처리하지않고 DFS를 가는것은 명백한 시간오버를 야기할수 있었다.

 

두번째로는 처음 그칸을 기준으로 오른쪽 밑으로 색종이를 채울때 가장 큰것을 채우는것이 제일 효율적인 방법인가?

이문제는 아래의 case를 생각해보자.

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

 

처음에 5를 놔두면 이맵은 더이상 채울수 없게된다. 따라서 5~1까지 모든사이즐 각 좌표에대해서 검증을 해야한다.

또한 DFS(y,x)로 접근하기보단 seq 를 만들어 y x로 바꾸는 것이 이전에 검사했던 곳을 반복하지 않는다.

 

또한 이문제에 특정조건은 처음에 1이 나와서 DFS를 수행햇을때 재귀를 거쳐 다시 원래지점으로 돌아온 직후

그 다음 칸으로 진행하면 안된다. 왜냐면 이전칸의 1을 지우지 못한채 다음 칸으로 가는것은 죽은 가지를 가는 것과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
 
 
public class B17136 {
    static int N = 10;
    static int Map[][] = new int[N][N];
    static int minValue;
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
 
        // 입력 끝
        int cnt_one = 0;
 
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < N; j++) {
                Map[i][j] = Integer.parseInt(st.nextToken());
                // 1이 남은 숫자
                if (Map[i][j] == 1)
                    cnt_one++;
            }
        }
 
        int[] colpaper = { 055555 };
        minValue = Integer.MAX_VALUE;
 
        DFS(00, cnt_one, Map, colpaper);
 
        if (minValue == Integer.MAX_VALUE) {
            System.out.println(-1);
        } else {
            System.out.println(minValue);
        }
 
    }
 
    public static void DFS(int seq, int cnt, int cnt_one, int[][] map, int[] colpaper) {
 
        if (minValue <= cnt)
            return;
 
        if (cnt_one == 0) {
            minValue = Math.min(minValue, cnt);
            return;
        }
 
        int[][] copyMap = new int[N][N];
        
        boolean isbreak = false;
        
        for (int s = seq; s < N * N; s++) {
            int i = s / N;
            int j = s % N;
            if (map[i][j] == 0 || map[i][j] == 2)
                continue;
 
            for (int size = 5; size >= 1; size--) {
                if (colpaper[size] == 0)
                    continue;
 
                if (isPosible(i, j, size, map)) {
                    // copyMap 만들어서 다음 dfs
                    for (int yy = 0; yy < N; yy++) {
                        System.arraycopy(map[yy], 0, copyMap[yy], 0, map[yy].length);
                    }
 
                    // copyMap에 2로 마킹하기
                    for (int yy = i; yy < i + size; yy++) {
                        for (int xx = j; xx < j + size; xx++) {
                            copyMap[yy][xx] = 2;
                        }
                    }
                    isbreak =true;
                    colpaper[size]--;
                    DFS(s, cnt + 1, cnt_one - size * size, copyMap, colpaper);
                    colpaper[size]++;
 
                }
 
            }
            if(isbreak) return;
 
        }
 
    }
 
    public static boolean isPosible(int y, int x, int size, int[][] map) {
 
        if (y + size > N || x + size > N)
            return false;
 
        for (int i = y; i < y + size; i++) {
            for (int j = x; j < x + size; j++) {
                if (map[i][j] != 1)
                    return false;
            }
        }
 
        return true;
    }
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
반응형

'ProgramSoliving' 카테고리의 다른 글

백준 : 1261  (0) 2020.02.08
백준 : 1238  (0) 2020.02.08
백준 : 1916  (0) 2020.02.07
백준 : 17142  (0) 2020.02.03
백준 : 17143  (0) 2020.02.03