기본적인 BFS의 구현은 노드와 방문 리스트를 이용한다.
BFS의 특성상 큐에 쌓이는 순서는 반드시 거리순이다.
연습 문제
1926: 그림
#include <iostream>
#include <queue>
using namespace std;
int canvas[501][501];
int visited[501][501];
int width, height;
pair<bool, int> bfs(int& _x, int& _y)
{
if (visited[_y][_x] || !canvas[_y][_x])
{
return make_pair(false, 0);
}
// 좌 상 우 하
int dx[4] = { -1, 0, 1, 0 };
int dy[4] = { 0, -1, 0, 1 };
queue<pair<int, int>> q;
int pic_size = 0;
visited[_y][_x] = 1;
q.push({ _x, _y });
while (!q.empty())
{
pair<int, int> cur = q.front();
q.pop();
pic_size++;
for (int i = 0; i < 4; ++i)
{
int nx = cur.first + dx[i];
int ny = cur.second + dy[i];
if (nx < 0 || nx >= width || ny < 0 || ny >= height || !canvas[ny][nx])
{
continue;
}
if (!visited[ny][nx])
{
visited[ny][nx] = 1;
q.push({ nx, ny });
}
}
}
return make_pair(true, pic_size);
}
int main()
{
ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int pic = 0, pic_size = 0;
cin >> height >> width;
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
int p;
cin >> p;
canvas[y][x] = p;
}
}
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
pair<int, int> t = bfs(x, y);
if (t.first)
{
pic++;
pic_size = pic_size > t.second ? pic_size : t.second;
}
}
}
cout << pic << '\n' << pic_size;
return 0;
}
가장 기초적인 BFS
2178: 미로 탐색
#include <iostream>
#include <string>
#include <queue>
using namespace std;
int maze[101][101];
int dist[101][101];
int width, height;
int bfs(int _x, int _y)
{
// 좌 상 우 하
int dx[4] = { -1, 0, 1, 0 };
int dy[4] = { 0, -1, 0, 1 };
queue<pair<int, int>> q;
dist[_y][_x] = 1;
q.push({ _x, _y });
while (!q.empty())
{
pair<int, int> cur = q.front();
q.pop();
for (int i = 0; i < 4; ++i)
{
int nx = cur.first + dx[i];
int ny = cur.second + dy[i];
if (nx < 0 || nx >= width || ny < 0 || ny >= height || !maze[ny][nx])
{
continue;
}
if (dist[ny][nx] == -1)
{
dist[ny][nx] = dist[cur.second][cur.first] + 1;
q.push({ nx, ny });
}
}
}
return dist[height-1][width-1];
}
int main()
{
ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int answer;
cin >> height >> width;
for (int y = 0; y < height; ++y)
{
string s;
cin >> s;
for (int x = 0; x < width; ++x)
{
maze[y][x] = s[x] - '0';
dist[y][x] = -1;
}
}
answer = bfs(0, 0);
cout << answer;
return 0;
}
간선의 가중치가 모두 1인 그래프의 최단거리는 BFS로 간단히 구현할 수 있다.
7576: 토마토
#include <iostream>
#include <queue>
using namespace std;
int field[1001][1001];
int dist[1001][1001];
int main()
{
ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int width, height, answer = 0;
// 좌 상 우 하
int dx[4] = { -1, 0, 1, 0 };
int dy[4] = { 0, -1, 0, 1 };
queue<pair<int, int>> q;
cin >> width >> height;
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
cin >> field[y][x];
dist[y][x] = 0;
if (field[y][x] == 1)
{
q.push({ x, y });
}
else if (field[y][x] == 0)
{
dist[y][x] = -1;
}
}
}
while (!q.empty())
{
pair<int, int> cur = q.front();
q.pop();
for (int i = 0; i < 4; ++i)
{
int nx = cur.first + dx[i];
int ny = cur.second + dy[i];
if (nx < 0 || nx >= width || ny < 0 || ny >= height || dist[ny][nx] >= 0 || field[ny][nx])
{
continue;
}
dist[ny][nx] = dist[cur.second][cur.first] + 1;
q.push({ nx, ny });
}
}
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (dist[y][x] == -1)
{
cout << "-1";
return 0;
}
answer = answer > dist[y][x] ? answer : dist[y][x];
}
}
cout << answer;
return 0;
}
시작점이 여러개인 BFS. 모든 시작점을 큐에 넣고 똑같이 BFS를 돌면 된다.
bfs가 끝난 후 최장거리 및 토마토의 고립여부 확인을 위해 완전 탐색을 실시한다.
7569: 토마토
#include <iostream>
#include <queue>
#include <tuple>
using namespace std;
int field[101][101][101];
int dist[101][101][101];
int main()
{
ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int width, height, depth, answer = 0;
// 좌 상 우 하 앞 뒤
int dx[6] = { -1, 0, 1, 0, 0, 0 };
int dy[6] = { 0, -1, 0, 1, 0, 0 };
int dz[6] = { 0, 0, 0, 0, 1, -1 };
queue<tuple<int, int, int>> q;
cin >> width >> height >> depth;
for (int z = 0; z < depth; ++z)
{
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
cin >> field[x][y][z];
dist[x][y][z] = 0;
if (field[x][y][z] == 1)
{
q.push({x, y, z});
}
else if (field[x][y][z] == 0)
{
dist[x][y][z] = -1;
}
}
}
}
while (!q.empty())
{
tuple<int, int, int> cur = q.front();
q.pop();
for (int i = 0; i < 6; ++i)
{
int nx = get<0>(cur) + dx[i];
int ny = get<1>(cur) + dy[i];
int nz = get<2>(cur) + dz[i];
if (nx < 0 || nx >= width || ny < 0 || ny >= height || nz < 0 || nz >= depth || dist[nx][ny][nz] >= 0 || field[nx][ny][nz])
{
continue;
}
dist[nx][ny][nz] = dist[get<0>(cur)][get<1>(cur)][get<2>(cur)] + 1;
q.push({ nx, ny, nz });
}
}
for (int z = 0; z < depth; z++)
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; ++x)
{
if (dist[x][y][z] == -1)
{
cout << "-1";
return 0;
}
answer = answer > dist[x][y][z] ? answer : dist[x][y][z];
}
}
}
cout << answer;
return 0;
}
3차원 확장판. x, y, z를 좀더 직관적으로 사용 및 볼수있게 수정함
4179: 불!
#include <iostream>
#include <string>
#include <queue>
using namespace std;
char field[1001][1001];
int dist_fire[1001][1001];
int dist_jh[1001][1001];
int main()
{
ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int width, height;
// 좌 상 우 하
int dx[4] = { -1, 0, 1, 0 };
int dy[4] = { 0, -1, 0, 1 };
queue<pair<int, int>> q_fire;
queue<pair<int, int>> q_jh;
cin >> height >> width;
for (int y = 0; y < height; ++y)
{
string s;
cin >> s;
for (int x = 0; x < width; ++x)
{
field[y][x] = s[x];
dist_fire[y][x] = -1;
dist_jh[y][x] = -1;
if (field[y][x] == 'F')
{
q_fire.push({ x,y });
dist_fire[y][x] = 0;
}
else if (field[y][x] == 'J')
{
q_jh.push({ x,y });
dist_jh[y][x] = 0;
}
}
}
while (!q_fire.empty())
{
pair<int, int> cur = q_fire.front();
q_fire.pop();
for (int i = 0; i < 4; ++i)
{
int nx = cur.first + dx[i];
int ny = cur.second + dy[i];
if (nx < 0 || nx >= width || ny < 0 || ny >= height)
{
continue;
}
if (field[ny][nx] == '#' || dist_fire[ny][nx] >= 0)
{
continue;
}
dist_fire[ny][nx] = dist_fire[cur.second][cur.first] + 1;
q_fire.push({ nx, ny });
}
}
while (!q_jh.empty())
{
pair<int, int> cur = q_jh.front();
q_jh.pop();
for (int i = 0; i < 4; ++i)
{
int nx = cur.first + dx[i];
int ny = cur.second + dy[i];
// 이번엔 범위를 벗어나면 탈출 성공.
if (nx < 0 || nx >= width || ny < 0 || ny >= height)
{
cout << dist_jh[cur.second][cur.first] + 1;
return 0;
}
if (field[ny][nx] == '#' || dist_jh[ny][nx] >= 0)
{
continue;
}
if (dist_fire[ny][nx] != -1 && dist_fire[ny][nx] <= dist_jh[cur.second][cur.first] + 1)
{
continue;
}
dist_jh[ny][nx] = dist_jh[cur.second][cur.first] + 1;
q_jh.push({ nx, ny });
}
}
cout << "IMPOSSIBLE";
return 0;
}
시작점이 두종류인 BFS. 지훈이와 불에 대한 BFS를 각각 수행함으로써 해결이 가능하다.
우선 불에대한 BFS를 수행해서 각 칸에 불이 전파되는 시간을 다 구해둔다.
이후 지훈이에 대한 BFS 수행시 각 칸의 값보다 작은 경우만 이동할 수 있다.
보통 이미 방문을 했거나 특정 값인 경우 continue로 건너뛰었는데 이 문제는 불이 붙은 시간을 확인해서 필요에 따라 continue를 하면 된다.
방문 테이블을 따로 쓴다.
두 종류의 BFS에서 BFS를 수행할 때 어느 한쪽이 독립적이지 않고 서로에게 영향을 준다면 위와 같은 방법으로는 풀 수 없고 백트래킹으로 해결해야한다.
1697: 숨바꼭질
#include <iostream>
#include <queue>
using namespace std;
int dist[100001];
int main()
{
ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
queue<int> q;
int n, k;
cin >> n >> k;
dist[n] = 0;
q.push(n);
while (!q.empty())
{
int pos = q.front();
q.pop();
if (pos == k)
{
cout << dist[pos];
return 0;
}
for (auto nxt : { pos - 1, pos + 1, pos * 2 })
{
if (nxt < 0 || nxt > 100000)
{
continue;
}
if (dist[nxt])
{
continue;
}
dist[nxt] = dist[pos] + 1;
q.push(nxt);
}
}
return 0;
}
수빈이가 갈 수있는 좌표인 x-1, x+1, x*2를 큐에 넣고 돌리면 된다.
범위가 넘는건 당연히 continue 처리를 하면 되고 방문여부도 확인해주면 된다.
기본 문제
1012: 유기농 배추
#include <iostream>
#include <queue>
using namespace std;
int visited[51][51];
int cabbage_field[51][51];
int width, height;
const int dx[4] = { -1, 0, 1, 0 };
const int dy[4] = { 0, -1, 0, 1 };
int bfs(int& x, int& y)
{
if (!cabbage_field[x][y] || visited[x][y])
{
return 0;
}
queue<pair<int, int>> q;
q.push({ x, y });
visited[x][y] = 1;
while (!q.empty())
{
pair<int, int> current_pos = q.front();
q.pop();
for (int i = 0; i < 4; ++i)
{
int nx = current_pos.first + dx[i];
int ny = current_pos.second + dy[i];
if (nx < 0 || nx >= width || ny < 0 || ny >= height)
{
continue;
}
if (!visited[nx][ny] && cabbage_field[nx][ny] == 1)
{
visited[nx][ny] = 1;
q.push({ nx, ny });
}
}
}
return 1;
}
int main()
{
ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int t;
cin >> t;
while (t--)
{
int k, answer = 0;
cin >> width >> height >> k;
for (int x = 0; x < width; ++x)
{
fill(cabbage_field[x], cabbage_field[x] + height, 0);
fill(visited[x], visited[x] + height, 0);
}
while (k--)
{
int x, y;
cin >> x >> y;
cabbage_field[x][y] = 1;
}
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; ++y)
{
answer += bfs(x, y);
}
}
cout << answer << '\n';
}
return 0;
}
기본적인 BFS
10026: 적록색약
#include <iostream>
#include <string>
#include <queue>
using namespace std;
string picture[101];
int ordinary_visited[101][101];
int special_visited[101][101];
const int dx[4] = { -1, 0, 1, 0 };
const int dy[4] = { 0, -1, 0, 1 };
int bfs(int (*visited)[101], int len, bool special = false)
{
int answer = 0;
for (int x = 0; x < len; ++x)
{
for (int y = 0; y < len; ++y)
{
if (visited[x][y]) {
continue;
}
queue<pair<int, int>> q;
visited[x][y] = 1;
q.push({ x, y });
answer++;
while (!q.empty())
{
pair<int, int> current_pos = q.front();
q.pop();
for (int i = 0; i < 4; ++i)
{
int nx = current_pos.first + dx[i];
int ny = current_pos.second + dy[i];
if (nx < 0 || nx >= len || ny < 0 || ny >= len)
{
continue;
}
// special
if (special)
{
// 153 = G(71) + R(82)
if (!visited[nx][ny] && ((picture[ny][nx] == picture[current_pos.second][current_pos.first])
|| (picture[ny][nx] + picture[current_pos.second][current_pos.first] == 153)))
{
visited[nx][ny] = 1;
q.push({ nx, ny });
}
}
// ordinary
else {
if (!visited[nx][ny] && (picture[ny][nx] == picture[current_pos.second][current_pos.first]))
{
visited[nx][ny] = 1;
q.push({ nx, ny });
}
}
}
}
}
}
return answer;
}
int main()
{
ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int n;
cin >> n;
for (int i = 0; i < n; ++i)
{
cin >> picture[i];
}
cout << bfs(ordinary_visited, n) << " ";
cout << bfs(special_visited, n, true);
return 0;
}
bfs 함수 재활용좀 해보려고 디폴트 매개변수를 썼더니 중간에 가독성이 확 떨어지는 한줄이 생겼다
보통의 경우는 보통의 bfs인데 적록색약인 경우 R=G로 봐야하기 때문에 둘의 아스키코드 값을 더해서 판별함
7562: 나이트의 이동
#include <iostream>
#include <queue>
using namespace std;
int table[301][301];
int bfs(pair<int, int>& start, pair<int, int>& dest, int& len)
{
// 좌2 상2 우2 하2 x, y
pair<int, int> move[8] = { {-2, 1}, {-2, -1}, {-1, -2}, {1, -2}, {2, -1}, {2, 1}, {1, 2}, {-1, 2} };
queue<pair<int, int>> q;
q.push(start);
table[start.first][start.second] = 0;
while (!q.empty())
{
pair<int, int> cur = q.front();
q.pop();
if (cur == dest)
{
return table[cur.first][cur.second];
}
for (int i = 0; i < 8; ++i)
{
int dx = cur.first + move[i].first;
int dy = cur.second + move[i].second;
if (dx < 0 || dx >= len || dy < 0 || dy >= len)
{
continue;
}
if (table[dx][dy] >= 0)
{
continue;
}
q.push({ dx, dy });
table[dx][dy] = table[cur.first][cur.second] + 1;
}
}
return 0;
}
void init_table(int len)
{
for (int i = 0; i < len; ++i)
{
fill(table[i], table[i] + len, -1);
}
}
int main()
{
ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int tc;
cin >> tc;
while (tc--)
{
int l;
pair<int, int> current, target;
cin >> l;
cin >> current.first >> current.second;
cin >> target.first >> target.second;
init_table(l);
cout << bfs(current, target, l) << '\n';
}
return 0;
}
기본적인 BFS 문제
5427: 불
#include <iostream>
#include <string>
#include <queue>
using namespace std;
int fire_dist[1001][1001];
int sk_dist[1001][1001];
string s[1001];
int main()
{
ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int tc;
const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, -1, 0, 1};
cin >> tc;
while (tc--)
{
int width, height;
queue<pair<int, int>> fire_q;
queue<pair<int, int>> sk_q;
bool isEscape = false;
cin >> width >> height;
for (int y = 0; y < height; ++y)
{
cin >> s[y];
for (int x = 0; x < width; ++x)
{
fire_dist[x][y] = 1000001;
sk_dist[x][y] = -1;
if (s[y][x] == '*')
{
fire_q.push({ x, y });
fire_dist[x][y] = 0;
}
else if (s[y][x] == '@')
{
sk_q.push({ x, y });
sk_dist[x][y] = 0;
}
}
}
while (!fire_q.empty())
{
pair<int, int> cur = fire_q.front();
fire_q.pop();
for (int i = 0; i < 4; ++i)
{
int nx = cur.first + dx[i];
int ny = cur.second + dy[i];
if (nx < 0 || nx >= width || ny < 0 || ny >= height)
{
continue;
}
if (s[ny][nx] == '#' || fire_dist[nx][ny] <= fire_dist[cur.first][cur.second] + 1)
{
continue;
}
fire_q.push({ nx, ny });
fire_dist[nx][ny] = fire_dist[cur.first][cur.second] + 1;
}
}
while (!sk_q.empty() && !isEscape)
{
pair<int, int> cur = sk_q.front();
sk_q.pop();
for (int i = 0; i < 4; ++i)
{
int nx = cur.first + dx[i];
int ny = cur.second + dy[i];
if (nx < 0 || nx >= width || ny < 0 || ny >= height)
{
cout << sk_dist[cur.first][cur.second] + 1 << '\n';
isEscape = true;
break;
}
if (s[ny][nx] == '#' || sk_dist[cur.first][cur.second] + 1 >= fire_dist[nx][ny] || sk_dist[nx][ny] >= 0)
{
continue;
}
sk_q.push({ nx, ny });
sk_dist[nx][ny] = sk_dist[cur.first][cur.second] + 1;
}
}
if (!isEscape)
{
cout << "IMPOSSIBLE" << '\n';
}
}
return 0;
}
불! 이랑 거의 동일한 문제임에도 불구하고 1시간 11분이 걸렸다.
구현의 95%정도는 30분안에 해결했는데 사소한 부분을 놓치니까 40분이 넘었다.
1000*1000 사이즈라서 최대값을 100만으로 줬어야하는데 1001로 줘서 25%에서 틀렸고 string 자체를 x,y 좌표방식으로 쓰려면 y,x 순서를 바꿔서 써야함에도 자꾸 틀리게 써서 오류도 많이 났다.
2583: 영역 구하기
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
int paper[101][101];
int visited[101][101];
const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, -1, 0, 1};
int main()
{
ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int width, height, n;
int p_num = 0;
queue<pair<int, int>> q;
vector<int> answer;
cin >> height >> width >> n;
while (n--)
{
int lx, ly, rx, ry;
cin >> lx >> ly >> rx >> ry;
for (int x = lx; x < rx; ++x)
{
for (int y = ly; y < ry; ++y)
{
paper[x][y] = 1;
}
}
}
for (int x = 0; x < width; ++x)
{
for (int y = 0; y < height; ++y)
{
if (paper[x][y] || visited[x][y])
{
continue;
}
queue<pair<int, int>> q;
int p_size = 0;
q.push({ x, y });
visited[x][y] = 1;
p_num++;
while (!q.empty())
{
pair<int, int> cur = q.front();
q.pop();
p_size++;
for (int i = 0; i < 4; ++i)
{
int nx = cur.first + dx[i];
int ny = cur.second + dy[i];
if (nx < 0 || nx >= width || ny < 0 || ny >= height)
{
continue;
}
if (paper[nx][ny] || visited[nx][ny])
{
continue;
}
q.push({ nx,ny });
visited[nx][ny] = 1;
}
}
answer.push_back(p_size);
}
}
sort(answer.begin(), answer.end());
cout << p_num << '\n';
for (auto& ans : answer)
{
cout << ans << " ";
}
return 0;
}
2667: 단지번호붙이기
#include <iostream>
#include <string>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
int visited[26][26];
const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, -1, 0, 1};
int main()
{
ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int n, h_num = 0;
string house[26];
queue<pair<int, int>> q;
vector<int> answer;
cin >> n;
for (int i = 0; i < n; ++i)
{
cin >> house[i];
}
for (int x = 0; x < n; ++x)
{
for (int y = 0; y < n; ++y)
{
if (!(house[x][y]-'0') || visited[x][y])
{
continue;
}
queue<pair<int, int>> q;
int h_size = 0;
q.push({ x, y });
visited[x][y] = 1;
h_num++;
while (!q.empty())
{
pair<int, int> cur = q.front();
q.pop();
h_size++;
for (int i = 0; i < 4; ++i)
{
int nx = cur.first + dx[i];
int ny = cur.second + dy[i];
if (nx < 0 || nx >= n || ny < 0 || ny >= n)
{
continue;
}
if (!(house[nx][ny]-'0') || visited[nx][ny])
{
continue;
}
q.push({ nx,ny });
visited[nx][ny] = 1;
}
}
answer.push_back(h_size);
}
}
sort(answer.begin(), answer.end());
cout << h_num << '\n';
for (auto& ans : answer)
{
cout << ans << '\n';
}
return 0;
}
기본적인 BFS
5014: 스타트링크
#include <iostream>
#include <queue>
using namespace std;
int visited[1000001];
int main()
{
ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
// f:층수 s:현재위치 g:목적지 u:위로 u층 d:아래로 d층
int f, s, g, u, d;
queue<int> q;
cin >> f >> s >> g >> u >> d;
fill(visited, visited + f + 1, -1);
q.push(s);
visited[s] = 0;
while (!q.empty())
{
int cur = q.front();
q.pop();
if (cur == g)
{
cout << visited[cur];
return 0;
}
if (cur - d >= 1)
{
if (visited[cur - d] == -1)
{
q.push(cur - d);
visited[cur - d] = visited[cur] + 1;
}
}
if (cur + u <= f)
{
if (visited[cur + u] == -1)
{
q.push(cur + u);
visited[cur + u] = visited[cur] + 1;
}
}
}
cout << "use the stairs";
return 0;
}
2468: 안전 영역
#include <iostream>
#include <queue>
using namespace std;
int area[101][101];
int visited[101][101];
const int dx[4] = { -1, 0, 1, 0 };
const int dy[4] = { 0, -1, 0, 1 };
void init_visited(int len)
{
for (int i = 0; i < len; ++i)
{
fill(visited[i], visited[i] + len + 1, 0);
}
}
int main()
{
ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int n, answer = 0;
int hst_h = 0;
queue<pair<int, int>> q;
cin >> n;
for (int x = 0; x < n; ++x)
{
for (int y = 0; y < n; ++y)
{
cin >> area[x][y];
hst_h = hst_h > area[x][y] ? hst_h : area[x][y];
}
}
for (int h = 0; h < hst_h; ++h)
{
int cnt = 0;
init_visited(n);
for (int x = 0; x < n; ++x)
{
for (int y = 0; y < n; ++y)
{
if (area[x][y] <= h || visited[x][y])
{
continue;
}
q.push({ x, y });
visited[x][y] = 1;
cnt++;
while (!q.empty())
{
pair<int, int> cur = q.front();
q.pop();
for (int i = 0; i < 4; ++i)
{
int nx = cur.first + dx[i];
int ny = cur.second + dy[i];
if (nx < 0 || nx >= n || ny < 0 || ny >= n)
{
continue;
}
if (area[nx][ny] <= h || visited[nx][ny])
{
continue;
}
q.push({ nx, ny });
visited[nx][ny] = 1;
}
}
}
}
answer = answer > cnt ? answer : cnt;
}
cout << answer;
return 0;
}
높이에 따라 bfs를 수행할 때 마다 값이 달라지기때문에 각 높이별로 bfs를 모두 수행해 주어 최고값을 산출해야 한다.
처음에 예제보고 n이하는 다 패스처리하고 예제 ac길래 매우 쉽다 생각했는데 반례랑 글좀 찾아보니 예제를 일부러 혼동하기 쉽게 만들어 둔것 같음. 아니면 내가 빡대가리거나
6593: 상범빌딩
#include <iostream>
#include <string>
#include <queue>
#include <tuple>
using namespace std;
string area[31][31];
int dist[31][31][31];
// 좌 우 상 하 앞 뒤
const int dx[6] = { -1, 0, 1, 0, 0, 0 };
const int dy[6] = { 0, -1, 0, 1, 0, 0 };
const int dz[6] = { 0, 0, 0, 0, -1, 1 };
int main()
{
ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
while (true)
{
int width, height, depth;
int answer = 0;
queue<tuple<int, int, int>> q;
// l, c, r
cin >> depth >> height >> width;
if (depth + width + height == 0)
{
return 0;
}
// dist 초기화
for (int x = 0; x < width; ++x)
{
for (int y = 0; y < height; ++y)
{
fill(dist[x][y], dist[x][y] + depth, -1);
}
}
// area 초기화
for (int z = 0; z < depth; ++z)
{
for (int y = 0; y < height; ++y)
{
cin >> area[z][y];
for (int x = 0; x < width; ++x)
{
if (area[z][y][x] == 'S')
{
q.push({ x, y, z });
dist[x][y][z] = 0;
}
}
}
}
while (!q.empty())
{
int curX = get<0>(q.front());
int curY = get<1>(q.front());
int curZ = get<2>(q.front());
q.pop();
if (area[curZ][curY][curX] == 'E')
{
answer = dist[curX][curY][curZ];
}
for (int i = 0; i < 6; ++i)
{
int nx = curX + dx[i];
int ny = curY + dy[i];
int nz = curZ + dz[i];
if (nx < 0 || nx >= width || ny < 0 || ny >= height || nz < 0 || nz >= depth)
{
continue;
}
if (area[nz][ny][nx] == '#' || dist[nx][ny][nz] >= 0)
{
continue;
}
q.push({ nx, ny, nz });
dist[nx][ny][nz] = dist[curX][curY][curZ] + 1;
}
}
if (answer)
{
cout << "Escaped in " << answer << " minute(s)." << '\n';
}
else
{
cout << "Trapped!" << '\n';
}
}
return 0;
}
토마토 3차원이랑 개념은 같음. 다행히 금방 짰음
'알고리즘 > 바킹독의 실전 알고리즘' 카테고리의 다른 글
[0x0B] 재귀 (0) | 2022.07.30 |
---|---|
[0x0A] DFS (0) | 2022.07.30 |
[0x08] 스택의 활용 (0) | 2022.07.25 |
[0x07] 덱(Deque) (0) | 2022.07.25 |
[0x06] 큐 (0) | 2022.07.25 |