ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • dfs를 이용한 완탐시, 방문 해제 모두 하고 return true
    실수모음 2023. 10. 24. 18:05
     

    9944번: NxM 보드 완주하기

    N×M 보드 위에서 할 수 있는 게임이 있다. 보드는 크기가 1×1인 정사각형 칸으로 나누어져 있다. 보드의 각 칸은 빈 칸 또는 장애물이다. 장애물은 아래 그림에선 어두운 사각형으로 표시되어져

    www.acmicpc.net

    틀린 코드(42번째 줄에서 바로 return true 하면 안됨)

    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
    #include <bits/stdc++.h>
    #define endl '\n' // don't use when you cover interactive problem
    #define all(v) v.begin(), v.end()
    #define MAX 31
    #define INF 1000
    #define AVAIL '.'
    #define WALL '*'
     
    using namespace std;
    typedef pair<intint> pi;
     
    int N, M;
    int ANS, FULL;
    char d[MAX][MAX];
    int dr[]{010-1};
    int dc[]{10-10};
     
    bool avail(int r, int c)
    {
        if(r < 0 || r >= N || c < 0 || c >= M || d[r][c] == WALL) return false;
        else return true;
    }
     
    bool dfs(int cr, int cc, int dep, int acc)
    {
        if(acc+1 == FULL){
            ANS  = min(ANS,  dep);
            return true;
        }
     
        for(int i = 0; i < 4; i++){
            if(!avail(cr+dr[i], cc+dc[i])) continue;
            
            int nr = cr;
            int nc = cc;
            while(avail(nr+dr[i], nc+dc[i])){
                d[nr][nc] = WALL;
                acc += 1;
                nr += dr[i];
                nc += dc[i];
            }
            if(dfs(nr, nc, dep+1, acc)) return true;
            
            while(cr != nr || cc != nc){
                nr -= dr[i];
                nc -= dc[i];
                d[nr][nc] = AVAIL;
                acc -= 1;
            }
        }
     
        return false;
    }
     
    int main() {
        ios::sync_with_stdio(false), cin.tie(0);
     
        int T = 1;
        while(cin >> N >> M){
            int cur_full = 0;
            for(int r = 0; r < N; r++){
                string tmp; cin >> tmp;
                for(int c = 0; c < M; c++){
                    d[r][c] = tmp[c];
                    if(d[r][c] == AVAIL) cur_full += 1;
                }
            }
            ANS  = INF;
            FULL = cur_full;
     
            for(int r = 0; r < N; r++){
                for(int c = 0; c < M; c++){
                    if(d[r][c] == WALL) continue;
                    
                    dfs(r, c, 00);
                }
            }
     
            cout << "Case " << T << ": " << ((ANS  == INF)? -1: ANS)  << endl;
            T += 1;
        }
        
     
        return 0;

    반례 출처 : https://www.acmicpc.net/board/view/35161

    10 10
    .........*
    ......*..*
    ..***.*..*
    ..***....*
    ..****...*
    ..****...*
    ..****...*
    ..****...*
    .........*
    .........*

    // Case 1: 11

    맞은 코드

    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
    #include <bits/stdc++.h>
    #define endl '\n' // don't use when you cover interactive problem
    #define all(v) v.begin(), v.end()
    #define MAX 31
    #define INF 1000
    #define AVAIL '.'
    #define WALL '*'
     
    using namespace std;
    typedef pair<intint> pi;
     
    int N, M;
    int ANS, FULL;
    char d[MAX][MAX];
    int dr[]{010-1};
    int dc[]{10-10};
     
    bool avail(int r, int c)
    {
        if(r < 0 || r >= N || c < 0 || c >= M || d[r][c] == WALL) return false;
        else return true;
    }
     
    bool dfs(int cr, int cc, int dep, int acc)
    {
        if(acc+1 == FULL){
            ANS  = min(ANS,  dep);
            return true;
        }
     
        for(int i = 0; i < 4; i++){
            if(!avail(cr+dr[i], cc+dc[i])) continue;
            
            bool flag = false;
            int nr = cr;
            int nc = cc;
            while(avail(nr+dr[i], nc+dc[i])){
                d[nr][nc] = WALL;
                acc += 1;
                nr += dr[i];
                nc += dc[i];
            }
            if(dfs(nr, nc, dep+1, acc)) flag = true;
            
            while(cr != nr || cc != nc){
                nr -= dr[i];
                nc -= dc[i];
                d[nr][nc] = AVAIL;
                acc -= 1;
            }
     
            if(flag) return true;
        }
     
        return false;
    }
     
    int main() {
        ios::sync_with_stdio(false), cin.tie(0);
     
        int T = 1;
        while(cin >> N >> M){
            int cur_full = 0;
            for(int r = 0; r < N; r++){
                string tmp; cin >> tmp;
                for(int c = 0; c < M; c++){
                    d[r][c] = tmp[c];
                    if(d[r][c] == AVAIL) cur_full += 1;
                }
            }
            ANS  = INF;
            FULL = cur_full;
     
            for(int r = 0; r < N; r++){
                for(int c = 0; c < M; c++){
                    if(d[r][c] == WALL) continue;
     
                    dfs(r, c, 00);
                }
            }
     
            cout << "Case " << T << ": " << ((ANS  == INF)? -1: ANS)  << endl;
            T += 1;
        }
        
     
        return 0;

    댓글

Designed by Tistory.