https://www.acmicpc.net/problem/16933
16933번: 벽 부수고 이동하기 3
첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 1,000), K(1 ≤ K ≤ 10)이 주어진다. 다음 N개의 줄에 M개의 숫자로 맵이 주어진다. (1, 1)과 (N, M)은 항상 0이라고 가정하자.
www.acmicpc.net
벽 부수고 이동하기2 문제에서 낮,밤이라는 조건만 추가된 문제이다.
낮인지 밤인지를 저장해줄 변수만 하나 더 추가하면 되는 문제라 풀이를 해결해내는 것이 벽 부수고 이동하기2 문제를 푼 사람이라면 그리 어려울 것 같지 않다.
다만, 맨 처음에 예제가 이해가 가지 않았다.
0010이면 낮,밤,낮,밤 이 순서로 생각한다면 3번째 인덱스에 도착했을 때는 낮이니깐 바로 벽을 부술 수 있고, 그러면 최단거리가 5가 아니라 4가 아닌가? 라고 생각하였다.
그러나 벽인지 확인하고 벽을 부수려고 할 때는 전의 칸의 낮,밤을 체크해야 한다.
즉, 인덱스로 표현해보자면 [0]->[1] 낮이면서 벽이 아니었기에 잘 이동하였고 밤이 된다.
[1]->[2]은 벽을 만난 상황인데 현재는 밤이라서 벽을 부술 수 없다.
그래서 하루를 기다리게 되는 것이다.
벽을 만난 경우와 벽을 만나지 않은 경우로 나눌 수 있고, 벽을 만나지 않은 경우는 그냥 지나가면 된다.
그러나 벽을 만난 경우는 우선, 벽을 깬 횟수가 k번보다 작은지 확인해야 한다.
k번보다 작아서 벽을 부술 수 있다면 낮인지 밤인지를 확인해야 한다.
낮이면 바로 깨면 되고, 밤이라면 하루 기다리면 된다.
dist배열을 업데이트해줄 때는 그 값이 초기화값인지를 확인해줘야 한다.
#include <iostream>
#include <algorithm>
#include <queue>
#include <tuple>
using namespace std;
#define X first
#define Y second
int n,m,k;
string area[1003];
int dist[3][12][1003][1003];
//{d,k,i,j} : (i,j)에 k번 벽을 부수고 도착했는데 d가 1이면 낮, d가 0이면 밤임
queue <tuple<int,int,int,int>> q;
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int BFS(){
while(!q.empty()){
int curD, curK, curX, curY;
tie(curD,curK,curX,curY) = q.front();
q.pop();
if(curX==n-1 && curY==m-1) return dist[curD][curK][curX][curY];
for(int dir=0; dir<4; dir++){
int nx = curX+dx[dir];
int ny = curY+dy[dir];
if(nx<0||nx>=n||ny<0||ny>=m) continue;
//벽을 만난 경우
if(area[nx][ny]=='1'){
//이미 k번 깼으면 더이상 깰 수 없음
if(curK>=k) continue;
//낮인 경우
if(curD){
if(dist[1-curD][curK+1][nx][ny]!=0) continue;
dist[1-curD][curK+1][nx][ny]=dist[curD][curK][curX][curY]+1;
q.push({1-curD,curK+1,nx,ny});
}
//밤이면 기다리면 됨
else{
if(dist[1-curD][curK][curX][curY]!=0) continue;
dist[1-curD][curK][curX][curY]=dist[curD][curK][curX][curY]+1;
q.push({1-curD,curK,curX,curY});
}
}
//벽이 아닌 경우 (그냥 가면 됨)
else if(area[nx][ny]=='0'){
if(dist[1-curD][curK][nx][ny]!=0) continue;
dist[1-curD][curK][nx][ny]=dist[curD][curK][curX][curY]+1;
q.push({1-curD,curK,nx,ny});
}
}
}
return -1;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cin>>n>>m>>k;
for(int i=0; i<n; i++) cin>>area[i];
dist[1][0][0][0]=1;
q.push({1,0,0,0});
cout<<BFS();
return 0;
}
'BOJ' 카테고리의 다른 글
[BOJ] 1759번 : 암호 만들기 (C++) (0) | 2023.04.06 |
---|---|
[BOJ] 16920번 : 확장 게임 (C++) (0) | 2023.04.03 |
[BOJ] 14442번 : 벽 부수고 이동하기 2 (C++) (0) | 2023.04.02 |
[BOJ] 13913번 : 숨바꼭질4 (C++) (0) | 2023.04.02 |
[BOJ] 1600번 : 말이 되고픈 원숭이 (C++) (0) | 2023.04.01 |