풀이법
1) BFS를 사용해서 풀 수 있는 문제이지만, 벽을 하나 허물 수 있다는 점에서 BFS가 익숙치 않은 사람들에게는 어려움을 줄 수 있는 문제이다.
2) 핵심은 이미 벽을 허물었는가를 확인하는 것 & visited 배열을 3차원으로 만드는 것이다.
3) visited 배열을 2차원으로 만들 경우 벽을 허물어서 지나간 곳과, 벽을 허물지 않았을 때 갈 수 있는 곳이 겹치게 되면, queue에 새로운 값을 push 할 수 없게 된다.
헷갈려 할만한 부분에 대해 주석을 자세히 달았으니, 이해를 기반한 공부에 도움이 되길 바란다.
#include <iostream>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
int n, m;
int arr[1001][1001];
int vx[4] = { 1,0,-1,0 };
int vy[4] = { 0,-1,0,1 };
int visited[1001][1001][2]; //벽 부신지 확인
int bfs()
{
queue < pair<int, pair<int, int>>> q;
q.push({ 1,{1,1 } }); //x=1, y=1, power=1(벽을 아직 안 허물었다)
visited[1][1][1] = 1; //처음 칸도 센다.
while (!q.empty())
{
int tx = q.front().first; //x좌표
int ty = q.front().second.first;//y좌표
int power = q.front().second.second; //벽 부실 수 있는지 여부
q.pop();
if (tx == n && ty == m)
{
return visited[n][m][power]; //반환 값
}
for (int i = 0; i < 4; i++)
{
int ux = tx + vx[i];
int uy = ty + vy[i];
if (ux<1 || ux>n || uy<1 || uy>m)
continue;
if (visited[ux][uy][power])
continue;
if (arr[ux][uy] == 0) //벽을 허물지 않고도 갈 수 있는 경우
{
visited[ux][uy][power] = visited[tx][ty][power]+1;
q.push({ ux,{uy,power} });
}
if (power && arr[ux][uy]==1) //벽을 허무는 경우
{
visited[ux][uy][power-1] = visited[tx][ty][power]+1;
q.push({ ux,{uy,power-1} });//power값을 0으로 만들어 구분해준다.
}
}
}
return -1;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
string a;
cin >> a;
for (int j = 0; j< a.size(); j++)
{
arr[i][j + 1] = a[j]-'0';
}
}
cout << bfs();
}
주의사항)
3차원 배열
다른 방법을 이용하여 문제를 풀 수 있으나, visited를 3차원 배열로 사용함으로서 클린한 코드를 짤 수 있다.
visited[x][y][power]에서 마지막 인자인 power는 1인 경우 벽을 허물 수 있는 것, 0인 경우 허물 수 없는 것을 의미한다. 벽을 허물지 않고서 지나갈 수 없는 해당 문제의 TC 1은 처음부터 벽을 허물지만, 만약 TC에 벽을 허물지 않고도 지나갈 수 있으나, 벽을 허물면 도착속도가 빨라지는 값이 들어오는 것을 고려하여 문제를 해결해야 한다.
배열을 3차원으로 해결하지 않은 경우 발생할 수 있는 문제점을 나타낸 좋은 Test Case가 있어 같이 첨부한다.
반례(Hidden TestCase) (출처: www.acmicpc.net/board/view/48468)
5 10
0000011000
1101011010
0000000010
1111111110
1111000000
정답: 14;
오답: -1 혹은 18;
'Coding_Test_C++' 카테고리의 다른 글
2017 팁스다운: 짝 지어 제거하기 (0) | 2021.05.04 |
---|---|
2019 카카오 개발자 겨울 인턴십 : 크레인 인형 뽑기 게임(C++) (0) | 2021.05.02 |
BaekJoon 1697번: 숨바꼭질 (0) | 2021.04.27 |
BaekJoon 4179번: 불! (0) | 2021.04.27 |
BaekJoon 7576번: 토마토 (0) | 2021.04.27 |