<Baekjoon> #16946 BFS_벽 부수고 이동하기 4 c++
이때까지 많이 풀어보았던 BFS 문제들 처럼 똑같이 BFS 함수를 구현하고 현재 위치가 WALL=1
이면 BFS탐색을 통해 갈 수 있는 PATH=0
의 개수를 count하고 리턴하여 그 수를 원래 WALL=1
이 있던 자리에 넣어주고 이 과정을 WALL
이 나올 때마다 반복해서 했다.
#include <iostream> #include <vector> #include <queue> #include <string.h> using namespace std; const int MAX = 1001; const int WALL = 1; const int PATH = 0; int N, M; int dy[4] = { 0,0,1,-1 }; int dx[4] = { 1,-1,0,0 }; vector<vector<int>> map; bool discovered[MAX][MAX]; int bfs(int y, int x) { int cnt = 1; queue<pair<int, int>>q; q.push(make_pair(y,x)); while (!q.empty()) { int cur_y = q.front().first; int cur_x = q.front().second; q.pop(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { int nx_y = cur_y + dy[i]; int nx_x = cur_x + dx[i]; if (nx_y < 0 || nx_x < 0 || nx_y >= N || nx_x >= M) continue; if (map[nx_y][nx_x] == PATH && !discovered[nx_y][nx_x]) { discovered[nx_y][nx_x] = true; q.push(make_pair(nx_y, nx_x)); cnt++; } } } } return cnt; } int main() { memset(discovered, false, sizeof(discovered)); cin >> N >> M; map = vector<vector<int>>(N, vector<int > (M)); for (int i = 0; i < N; i++) { string tmp; cin >> tmp; for (int j = 0; j < M; j++) { int tmp2 = tmp[j] - '0'; map[i][j] = tmp2; } } for (int i = 0; i < N; i++) { for (int j = 0; j < M; j++) { if (map[i][j] == WALL) { int ans = bfs(i, j); ans %= 10; map[i][j] = ans; memset(discovered, false, sizeof(discovered)); } } } for (int i = 0; i < N; i++) { for (int j = 0; j < M; j++) printf("%d", map[i][j]); printf("\n"); } return 0; }
그런데 시간 초과가 나고 다른 포스팅을 참고 하여 다른 풀이로 풀었다.
접근 방법을 다르게 하여, 일단 PATH Blob
의 개수를 count
하여 저장하고,WALL
이 나왔을 때 그 WALL
과 상,하,좌,우로 인접한 곳에 PATH Blob
이 있다면 그 수를 더해준다.
PathBlob 채우기
맵의 전체 부분을 탐색 하다가PATH=0
을 만나면dfs
함수를 호출하여 해당PATH
과 인접한 모든PATH
를count
하여 그 크기를 PathBlob에 저장한다.
위 예시에서
int pathBlobSize=6
이고
blobNum[0][2]=blobNum[0][3]=0
,
blobNum[1][0]=blobNum[1][1]=blobNum[2][0]=1
,
blobNum[2][2]=2
,
blobNum[2][4]=3
,
blobNum[3][1]=4
,
blobNum[3][3]=5
이 저장된다.
2.벽과 상,하,좌,우로 인접한 PathBlob을 찾아 더해준다
answer[i][j] += pathBlob[blobNum[nx_y][nx_x]]; //nx_y, nx_x 는 현재 위치 (i,j)를 기준으로 상,하,좌,우의 좌표
여기서 문제점이 생기게 되는데 왼쪽과 위쪽에 인접한pathBlob
은 같은blob
이기 때문에 한 번만 더해주어야 한다.그래서 한 번 pathBlob을 방문하면 이미 방문했다는 표시로
set<int> Search
를 이용한다.
WALL
과 인접한PATH
를 찾아 이pathBlob
의 크기를 더해줄 때 몇 번 째pathBlob
인지 즉blobNum
을 Search에 넣어준다.Search.insert(blobNum[nx_y][nx_x]); answer[i][j] += pathBlob[blobNum[nx_y][nx_x]];
그리고 다음에 다시
WALL
과 인접한PATH
를 찾았을 때 이PATH
가 이미 더해준PATH
인지를 탐색하기 위해if (Search.find(blobNum[nx_y][nx_x]) == Search.end())
다음과 같이
Search
에 현재 더하려고 하는blobNum
이 있는지 보고 없으면 크기를 더해준다
(set.find()
연산에서 찾는 값이 없으면set.end()
를return
한다)
전체 코드 (변수가 많아 헷갈리지만 차근 차근 본다)
#include <iostream> #include <vector> #include <queue> #include <string.h> #include <set> using namespace std; const int WALL = 1; const int PATH = 0; const int MAX = 1001; int N, M; int dy[4] = { 0,0,1,-1 }; int dx[4] = { 1,-1,0,0 }; vector<int> pathBlob; vector<vector<int>> map; int blobNum[MAX][MAX]; int discovered[MAX][MAX]; int answer[MAX][MAX]; int pathBlobSize = 0; void dfs(int y, int x) { discovered[y][x] = true; blobNum[y][x] = pathBlobSize; int cnt = 1; queue<pair<int, int>> q; q.push(make_pair(y, x)); while (!q.empty()) { int cur_y = q.front().first; int cur_x = q.front().second; q.pop(); for (int i = 0; i < 4; i++) { int nx_y = cur_y + dy[i]; int nx_x = cur_x + dx[i]; if (nx_y < 0 || nx_x < 0 || nx_y >= N || nx_x >= M) continue; if (map[nx_y][nx_x] == PATH && !discovered[nx_y][nx_x]) { q.push(make_pair(nx_y, nx_x)); discovered[nx_y][nx_x] = true; blobNum[nx_y][nx_x] = pathBlobSize; cnt++; } } } pathBlob.push_back(cnt); } void soultion() { memset(answer, 0, sizeof(answer)); memset(blobNum, -1, sizeof(blobNum)); memset(discovered, false, sizeof(discovered)); cin >> N >> M; map = vector<vector<int>>(N, vector<int >(M)); //input data to map for (int i = 0; i < N; i++) { string tmp; cin >> tmp; for (int j = 0; j < M; j++) { int num = tmp[j] - '0'; map[i][j] = num; } } //find PATH area for (int i = 0; i < N; i++) { for (int j = 0; j < M; j++) { if (map[i][j] == PATH && !discovered[i][j]) { dfs(i, j); pathBlobSize++; } } } //find WALL and Add neighbour PATH area for (int i = 0; i < N; i++) { for (int j=0; j < M; j++) { if (map[i][j] == WALL) { set<int> Search; for (int k = 0; k < 4; k++) { int nx_y = i + dy[k]; int nx_x = j + dx[k]; if (nx_y < 0 || nx_x < 0 || nx_y >= N || nx_x >= M) continue; if (map[nx_y][nx_x] == PATH) { if (Search.find(blobNum[nx_y][nx_x]) == Search.end()) { Search.insert(blobNum[nx_y][nx_x]); answer[i][j] += pathBlob[blobNum[nx_y][nx_x]]; } } } answer[i][j] += 1; answer[i][j] %= 10; } } } for (int i = 0; i < N; i++) { for (int j = 0; j < M; j++) { printf("%d", answer[i][j]); } printf("\n"); } } int main() { soultion(); return 0; }
Author And Source
이 문제에 관하여(<Baekjoon> #16946 BFS_벽 부수고 이동하기 4 c++), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@kimmy/Baekjoon-16946-BFS벽-부수고-이동하기-4저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)