728x90
https://www.acmicpc.net/problem/1600
bfs 문제로 1년만에 다시 풀어보았다. 흥미로운 점은 과거의 나는 k값을 주어진 개수만큼 넣어놓고 --한 반면 오늘의 나는 0으로 두고 하나씩 늘려나갔다는 것과 지금은 큐 내에서 cnt 를 늘렸는데 과거에선 dis 배열을 만들어서 거기에다가 값을 넣어놓았다. 둘 다 할 수 있는 방법이지만 왜 굳이 저렇게 했는지..
그런데 dis배열에 넣는 것이 훨씬 시간이 짧았다... 이걸로 다익스트라처럼 가지치기를 하는 것도 아니고 같은 순회를 할 탠데 왜 시간이 덜 걸리는지 모르겠다.
각설하고 이 문제는 말처럼 이동할 수 있는 k이동을 20번 남았을 때와 10번 남았을 때의 상황을 따로 가정하여 방문 표시를 해야한다. 때문에 3차원 visited 배열을 선언하여 순회해야한다.
위 3차원 visited만 떠올리면 엄청 어려울 것은 없는 문제이다. 하지만 이것을 떠올리기가 어렵다.
#include <iostream>
#include <queue>
using namespace std;
const int MAX = 201;
const int KMAX = 31;
bool visited[MAX][MAX][KMAX];
int board[MAX][MAX];
int N, M, K;
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
int kx[] = {-1,-2,-2,-1,1,2,1,2};
int ky[] = {2,1,-1,-2,-2,-1,2,1};
bool range(int x, int y){
return (x < N && x > -1 && y < M && y > -1);
}
int bfs(){
queue<pair<pair<int, int>, pair<int, int>>> q;
q.push({{0,0}, {0, 0}});
while(!q.empty()){
int x = q.front().first.first;
int y = q.front().first.second;
int k = q.front().second.first;
int cnt = q.front().second.second;
q.pop();
if(x == N - 1 && y == M - 1){
return cnt;
}
for(int i = 0; i < 4; i++){
int nx = x + dx[i];
int ny = y + dy[i];
if(range(nx, ny) && !visited[nx][ny][k] && board[nx][ny] == 0){
q.push({{nx, ny}, {k, cnt + 1}});
visited[nx][ny][k] = true;
}
if(k < K){
for(int i = 0; i < 8; i++){
int nx = x + kx[i];
int ny = y + ky[i];
if(range(nx, ny) && !visited[nx][ny][k + 1] && board[nx][ny] == 0){
visited[nx][ny][k + 1] = true;
q.push({{nx, ny}, {k + 1, cnt + 1}});
}
}
}
}
}
return -1;
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin >> K >> M >> N;
for(int i = 0; i < N; i++){
for(int j = 0; j < M; j++){
cin >> board[i][j];
}
}
cout << bfs() << '\n';
}
'백준 문제 풀이' 카테고리의 다른 글
백준 1516번 - 게임 개발 (C++, 위상정렬, 다이나믹 프로그래밍) (0) | 2024.06.22 |
---|---|
백준 1103번 - 게임(C++, dfs를 DP로 최적화) (1) | 2024.06.21 |
백준 1092번 - 배(c++) (0) | 2024.06.14 |
백준 8980번 - 택배 (C++) (1) | 2024.06.13 |
백준 1931번 - 회의실 배정(C++) (0) | 2024.06.12 |