胖胖的牛牛(优先队列BFS)
思路
- 优先队列BFS, 按照起点到每个点的转弯次数从小到大排序
- 每次取出队头元素, 令
st[x][y] = true;
,代表每次出队的元素的转弯次数已经确定
- 每次入队的点的转弯次数未必是最少的, 可能从别的路径走到该点的转弯次数更少, 所以入队的时候不要令st[a][b] = true
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, -1, 1};
const double eps = 1e-6;
const int N = 100 + 10;
char g[N][N];
int n, m;
bool st[N][N];
struct Node
{
int x, y;
int prex, prey;
int dis; // 转弯次数
bool operator<(const Node &w) const // 优先队列中按照转弯次数从小到大排列
{
return dis > w.dis;
}
};
int bfs()
{
int sx, sy, ex, ey;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (g[i][j] == 'A')
sx = i, sy = j;
if (g[i][j] == 'B')
ex = i, ey = j;
}
}
priority_queue<Node> q;
q.push({sx, sy, sx, sy, 0}); // 起点的上一个点定义为起点自己
st[sx][sy] = true; // (sx,sy)的最少转弯次数已经确定
while (!q.empty())
{
Node t = q.top();
q.pop();
int x = t.x, y = t.y;
if (x == ex && y == ey)
return t.dis;
// 每次出队的元素的转弯次数已经确定
st[x][y] = true;
for (int i = 0; i < 4; i++)
{
int a = x + dx[i], b = y + dy[i];
if (a < 0 || a > n - 1 || b < 0 || b > n - 1)
continue;
if (g[a][b] == 'x')
continue;
if (st[a][b])
continue;
int add = 0;
if (t.prex != a && t.prey != b) // 转弯了
add++;
// 每次入队的点的转弯次数未必是最少的, 可能从别的路径走到该点的转弯次数更少, 所以入队的时候不要令st[a][b] = true
q.push({a, b, x, y, t.dis + add});
}
}
return -1;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> g[i][j];
}
}
cout << bfs() << '\n';
return 0;
}