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



DFS를 통해 좌표에서 색종이를 붙일 수 있는지 없는지 확인을 한 뒤에

붙일 수 있다면 재귀호출을 하고 모두 붙였는지를 확인하는 방향으로 문제를 해결했다.


이전에 색종이를 모든 붙인 개수보다 현재 색종이를 붙인 개수가 더 많아지거나

모든 색종이를 붙였을 경우에는 더이상 호출하지 않고 종료시킬 수 있도록 했다.


1과 0이 존재하는 paper 변수를(입력 받은 2차원 배열 종이 공간) 매개변수로 함수를 연속으로 호출해서 시간 초과는 아니지만 오래 걸리는 것 같다.

전역으로 처리하기가 어려워서 이 부분은 좀 더 고민을 하고 코드를 수정해야 할 것 같다.


dfs함수 부분의 주요 로직을 살펴보면

다음 dfs 함수를 호출하기 전에 check변수를 통해 현재 종이에 붙일 수 있는 좌표인 y,x좌표를 구할 수 있도록 했다.

여기서 실수한 부분은 y,x좌표를 구했으면 바로 나와야 하는데 그 지점에서 다시 dfs 함수를 호출해서 무한 루프를 돌았다.


그리고 1~5까지 사용할 수 있는 색종이의 개수가 5개 이기 때문에, 붙이려는 색종이의 개수가 남았는지를 먼저 확인하고 

해당 길이를 붙일 수 있는지 확인 했다.(붙이려는 칸의 범위가 벗어나거나 0이 있는지 확인)



백트래킹을 진행하는 과정에서 잘못 구현해서 무한 루프가 돌았는데

주어진 시간안에 해결하지 못해서 문제 해결 방향을 세우는 연습을 더 해야 할 것 같다...



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
#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
 
int ans=-1;
int color_cnt[6]={0,5,5,5,5,5};
 
bool prove(vector<vector<int>> paper){
    for(int i=0;i<10;i++){
        for(int j=0;j<10;j++){
            if(paper[i][j])
                return false;
        }
    }
    return true;
}
 
bool zero_exist(int y,int x,int len,vector<vector<int>> paper){
    
    for(int i=0;i<len;i++)
        for(int j=0;j<len;j++){
            if(y+i>=10 || x+j>=10)
                return true;
            
            if(paper[y+i][x+j]==0)
                return true;
        }
    
    return false;
}
 
//0을 1로, 1을 0으로 세팅(색종이 붙이거나, 붙인 색종이 원상복귀 용도)
vector<vector<int>> set_paper(int y,int x,int len,vector<vector<int>> paper){
    for(int i=0;i<len;i++)
        for(int j=0;j<len;j++)
            paper[y+i][j+x]=(paper[y+i][j+x])? 0:1;
    
    return paper;
    
}
void dfs(int y,int x,int cnt,vector<vector<int>> paper){
    
    
    if(ans!=-1 && cnt>ans)
        return;
    
    //모두 붙였는지 확인(모두 0인지)
    if(prove(paper)){
        ans=(ans==-1)? cnt:min(ans,cnt);
        return;
    }
    
    
    /*
      1이 존재하는 좌표(y,x) 확인
      3중 for문으로 다시 색종이 붙이는 작업 진행하면 무한 루프돈다.
    */
    bool check=false;
    for(y=0;y<10;y++){
        for(x=0;x<10;x++){
            if(paper[y][x]){
                check=true;
                break;
            }
        }
        if(check)
            break;
    }
    
    for(int len=5; len>0; len--){
        
        //색종이 붙일 수 있는지 확인
        if(color_cnt[len]==0)
            continue;
        
        //붙이려는 색종이 공간에 0이 있거나 범위 벗어나는지 확인
        if(zero_exist(y,x,len,paper))
            continue;
        
        //해당 길이(사이즈)만큼 색종이 사용
        paper=set_paper(y,x,len,paper); //해당 길이만큼 0으로
        color_cnt[len]--;
        dfs(y,x,cnt+1,paper);
        
        paper=set_paper(y,x,len,paper); //해당 길이만큼 1로
        color_cnt[len]++;
        
    }
}
int main(){
    
    vector<vector<int>> paper(10,vector<int>(10,0));
    for(int i=0;i<10;i++)
        for(int j=0;j<10;j++){
            cin>>paper[i][j];
        }
    
    dfs(0,0,0,paper);
    cout<<ans<<endl;
    return 0;
}
 
cs


'알고리즘(BOJ) > DFS' 카테고리의 다른 글

백준 16198번 - 에너지 모으기  (0) 2019.07.18
백준 9521번 - 색칠 공부  (0) 2019.06.18
백준 14502번 - 연구소  (0) 2019.03.30
백준 2668번 - 숫자 고르기  (3) 2019.03.29
백준 15686번 - 치킨 배달  (0) 2018.10.15

+ Recent posts