1020 胖胖的牛牛 优先队列 bfs 转向时上上次xy与当前xy都不同

 链接:https://ac.nowcoder.com/acm/problem/208246
来源:牛客网

题目描述

每逢佳节胖三斤,牛牛在过去的节日里长胖了,连拐弯都困难,甚至会卡在门上,所以他很讨厌拐弯。给你一个N*N(2≤N≤100)的方格中,‘x’表示障碍,‘.’表示没有障碍(可以走),牛牛可以从一个格子走到他相邻的四个格子,但是不能走出这些格子。问牛牛从A点到B点最少需要转90度的弯几次。



输入描述:

第一行一个整数:N,下面N 行,每行N 个字符,只出现字符:‘.’,‘x’,‘A’,‘B’;表示上面所说的矩阵格子,每个字符后有一个空格。

输出描述:

一个整数:最少转弯次数。如果不能到达,输出-1。
示例1

输入

复制
3
. x A
. . .
B x .

输出

复制
2

备注:

开始和结束时的方向任意。

分析

优先队列+bfs。优先处理转向次数最少的。

转向时,和上上次的位置的x和y都不一样。距离+1

走过的点不用再走了。

#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;
}

 

posted @ 2022-08-16 18:00  er007  阅读(29)  评论(0编辑  收藏  举报