출처: https://bumcrush.tistory.com/182 [맑음때때로 여름]
https://www.acmicpc.net/problem/3055
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
const int MAX = 50;
typedef struct
{
int x, y;
} Water;
typedef struct
{
int x, y;
} Dir;
typedef struct
{
int x, y, cnt;
} HedgeHog;
Dir dirMove[4] = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};
queue<Water> q;
string graph[MAX];
int R, C;
int start_X, start_Y, end_X, end_Y;
bool visited[MAX][MAX];
// bool waterVisited[MAX][MAX];
int waterDay[MAX][MAX];
void flood()
{
waterDay[end_X][end_Y] = 2500;
for (int i = 0; i < R; i++)
{
for (int j = 0; j < C; j++)
{
if (graph[i][j] == '*')
{
q.push({i, j});
// waterVisited[i][j] = true;
}
}
}
while (!q.empty())
{
int curX = q.front().x;
int curY = q.front().y;
q.pop();
for (int i = 0; i < 4; i++)
{
int nextX = curX + dirMove[i].x;
int nextY = curY + dirMove[i].y;
if (0 <= nextX && nextX < R && 0 <= nextY && nextY < C && graph[nextX][nextY] == '.' && !waterDay[nextX][nextY])
{
waterDay[nextX][nextY] = waterDay[curX][curY] + 1;
// waterVisited[nextX][nextY] = true;
q.push({nextX, nextY});
}
}
}
}
int bfs(int x, int y, int cnt)
{
queue<HedgeHog> p;
p.push({x, y, cnt});
visited[x][y] = true;
while (!p.empty())
{
int curX = p.front().x;
int curY = p.front().y;
int curCnt = p.front().cnt;
// cout<<curX<<" "<<curY<<" "<<curCnt<<"\n";
p.pop();
if (curX == end_X && curY == end_Y)
{
return curCnt;
}
for (int i = 0; i < 4; i++)
{
int nextX = curX + dirMove[i].x;
int nextY = curY + dirMove[i].y;
if (0 <= nextX && nextX < R && 0 <= nextY && nextY < C && !visited[nextX][nextY])
{
if (graph[nextX][nextY] == '.' || graph[nextX][nextY] == 'D')
{
if (curCnt + 1 < waterDay[nextX][nextY] || waterDay[nextX][nextY] == 0)
{
p.push({nextX, nextY, curCnt + 1});
visited[nextX][nextY] = true;
}
}
}
}
}
return 0;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cin >> R >> C;
for (int i = 0; i < R; i++)
{
cin >> graph[i];
}
for (int i = 0; i < R; i++)
{
for (int j = 0; j < C; j++)
{
if (graph[i][j] == 'S')
{
start_X = i;
start_Y = j;
// graph[i][j]='.';
}
if (graph[i][j] == 'D')
{
end_X = i;
end_Y = j;
}
}
}
flood();
// for(int i=0;i<R;i++){
// for(int j=0;j<C;j++){
// cout<<waterDay[i][j]<<" ";
// }
// cout<<"\n";
// }
int ans = bfs(start_X, start_Y, 0);
if (!visited[end_X][end_Y])
cout << "KAKTUS";
else
{
cout << ans;
}
}
//이거 풀리면 불! 문제 풀어보자
이 문제를 푸는데 정말 오랜 시간이 걸렸다.
최단거리를 구할 때는 반드시 bfs로 풀어야 한다는 것을 알면서도 dfs로 만들었다.
void dfs(int x, int y, int cnt) {
visited[x][y]=true;
if (x==end_X&&y==end_Y) {
ans.push_back(cnt);
return;
}
for (int i=0;i<4;i++) {
int nextX=x+dirMove[i].x;
int nextY=y+dirMove[i].y;
if (0<=nextX&&nextX<R&&0<=nextY&&nextY<C&&!visited[nextX][nextY]) {
if (graph[nextX][nextY]=='.'||graph[nextX][nextY]=='D') {
for (int i=0;i<R;i++) {
tmpGraph[i]=graph[i];
}
bfs();
dfs(nextX, nextY, cnt+1);
for (int i=0;i<R;i++) {
graph[i]=tmpGraph[i];
}
}
}
//최단거리를 찾는거니까 이 부분도 bfs와 같이 구현해주어야 하는것 같은데......
}
}
이렇게 해도 테스트 케이스들은 모두 통과한다. 내 생각에는 이렇게 하면 도착지점에 도착하는 모든 경우의 수들이 vector ans 속에 들어갈 것이라 생각했지만, 처음 dfs를 돌 때 visited가 true가 돼서 사실상 저 vector 속에 들어가게 되는 답안은 단 하나뿐이게 된다. 때문에 dfs로 최단거리 문제를 접근해서는 안되는 것이다.
그 이후 bfs 식으로 코드를 구성하였지만 그럼에도 계속해서 '메모리 초과' 오류가 났다. 이 오류의 이유를 찾는데 정말 많은 시간이 들었다.
메모리 초과가 발생한 이유는 bfs내에서 return 0를 하지 않았기 때문이다..... 도착하지 못하는 경우가 분명히 생기는데 이때는 return 0 구문을 빼먹으면 return 값이 없게 된다. 정말 많이 삽질했다.....
백준 2636 치즈(bfs) (0) | 2020.08.26 |
---|---|
백준 1963 소수 경로(에스테라노스의 체, bfs) (0) | 2020.08.19 |
백준 14891 톱니바퀴(구현, 시뮬레이션) (0) | 2020.08.13 |
백준 2644 촌수계산(bfs) (0) | 2020.08.11 |
백준 2250 트리의 높이와 너비(dfs, inorder traversal) (0) | 2020.08.06 |
댓글 영역