Problem link: https://www.acmicpc.net/problem/6087
BFS 아이디어를 잘 응용하면 쉽게 풀어 줄 수 있다.
BFS의 장점은 간선에 가중치가 없는 그래프라면 곧 방문순서가 경로의 길이가 된다는 점이다.
다시 말하면, 간선에 가중치가 없으므로 BFS 순서에 따라 정점을 방문하다가 최초로 목적지 정점을 탐색하게 되는 순간이 곧 최단 경로이다.
위의 성질을 마음에 새기고, 본 문제의 풀이를 기술하면 아래와 같다.
#include <cstdio>
#include <utility>
#include <queue>
#include <vector>
using namespace std;
const int kMaxW = 100;
const int kMaxH = 100;
vector<pair<int, int> > LASERS;
int W;
int H;
int VISIT[kMaxH][kMaxW];
char BOARD[kMaxH][kMaxW];
queue<pair<int, int> > Q;
const int dr[4] = { -1, 0, 1, 0 };
const int dc[4] = { 0, 1, 0, -1 };
void Span(const int row, const int col, const int dir, const int cost)
{
int nrow = row;
int ncol = col;
while (true)
{
nrow += dr[dir];
ncol += dc[dir];
if (0 > nrow || nrow >= H || 0 > ncol || ncol >= W || BOARD[nrow][ncol] == '*')
{
break;
}
if (VISIT[nrow][ncol] == -1)
{
VISIT[nrow][ncol] = cost;
Q.emplace(nrow, ncol);
}
}
}
int Solve(void)
{
VISIT[LASERS[0].first][LASERS[0].second] = 0;
Q.push(LASERS[0]);
for (int dir = 0; dir < 4; ++dir)
{
Span(LASERS[0].first, LASERS[0].second, dir, 0);
}
while (!Q.empty())
{
int row = Q.front().first;
int col = Q.front().second;
Q.pop();
if (row == LASERS[1].first && col == LASERS[1].second)
{
return VISIT[row][col];
}
for (int dir = 0; dir < 4; ++dir)
{
Span(row, col, dir, VISIT[row][col] + 1);
}
}
return -1;
}
int main(void)
{
// Read Input
scanf(" %d %d", &W, &H);
for (int row = 0; row < H; ++row)
{
for (int col = 0; col < W; ++col)
{
scanf(" %c", &BOARD[row][col]);
if (BOARD[row][col] == 'C')
{
LASERS.emplace_back(row, col);
}
VISIT[row][col] = -1;
}
}
// Solve
printf("%d\n", Solve());
return 0;
}