짱아의 개발 기록장

백준 16946번. 벽 부수고 이동하기 4(c++) / bfs 응용 본문

Algorithm/Baekjoon

백준 16946번. 벽 부수고 이동하기 4(c++) / bfs 응용

jungahshin 2020. 8. 24. 14:58
반응형

처음에 아이디어가 잘 생각나지 않아 애를 먹었다.

그냥 일일히 bfs로 돌게 되면 당연히 시간초과가 날 것 같아서

무언가를 저장하고 그것을 가져다가 쓰는 방식으로 구현을 해야겠다고 생각했다.

 

따라서, 인접한 영역들을 idx로 표시해두고 해당 idx의 영영의 크기를 따로 vector에 저장해두었다.

아마 코드를 보면 더 이해하기 쉬울 것이라 생각한다.

 

 

코드 첨부

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
// 벽 부수고 이동하기 4
#include <iostream>
#include <queue>
#include <map>
#include <cstring>
 
using namespace std;
 
int n, m;
string s;
int wall[1001][1001= {0, };
int AREA[1001][1001]; // 영역의 idx
vector<int> AREA_NUM; // 영역의 크기
int final = 0;
int dx[4= {00-11};
int dy[4= {-1100};
 
void check()
{
    int visited[1001][1001= {0, };
    queue<pair<pair<intint>int>> q;
    int idx = 0// 인접 영역 번호매기기
 
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(!visited[i][j] && wall[i][j]==0){
                vector<pair<intint>> temp;
                q.push(make_pair(make_pair(i, j), 1));
                int area = 1;
 
                while(!q.empty()){
                    int x = q.front().first.first;
                    int y = q.front().first.second;
                    int num = q.front().second;
                    visited[x][y] = 1;
                    temp.push_back(make_pair(x, y));
                    q.pop();
 
                    for(int k=0; k<4; k++){
                        int nx = x+dx[k];
                        int ny = y+dy[k];
                        if(0<=nx && nx<&& 0<=ny && ny<&& !visited[nx][ny]){
                            if(wall[nx][ny]==0){
                                area++;
                                visited[nx][ny] = 1;
                                q.push(make_pair(make_pair(nx, ny), num+1));
                            }
                        }
                    }
                }
 
                for(int k=0; k<temp.size(); k++){
                    AREA[temp[k].first][temp[k].second] = idx;
                }
                AREA_NUM.push_back(area);
                idx++;
            }
        }
    }
}
 
void count()
{
    for(int i=0; i<n; i++){
        string S;
        for(int j=0; j<m; j++){
            if(wall[i][j]==1){
                map<intint> M;
                int num = 0;
 
                for(int k=0; k<4; k++){
                    int nx = i+dx[k];
                    int ny = j+dy[k];
 
                    if(0<=nx && nx<&& 0<=ny && ny<m){
                        if(wall[nx][ny]==0 && M.count(AREA[nx][ny])==0){
                            M[AREA[nx][ny]] = 1;
                            num += AREA_NUM[AREA[nx][ny]];
                        }
                    }
                }
 
                S += to_string((num+1)%10);
            }else{
                S += "0";
            }
        }
        cout<<S<<"\n";
    }
}
 
int main()
{
    cin>>n>>m;
    for(int i=0; i<n; i++){
        cin>>s;
        for(int j=0; j<s.size(); j++){
            wall[i][j] = s[j]-'0';
        }
    }
 
    memset(AREA, -1sizeof(AREA));
    check();
    count();
 
    return 0;
}
cs

 

 

문제 첨부

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

 

16946번: 벽 부수고 이동하기 4

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 한 칸에서 다른 칸으로 이동하려면, 두 칸이 인접해야 한다. 두 칸이 �

www.acmicpc.net

반응형
Comments