HDU 1728 逃离迷宫(拐弯问题,对BFS最优解的新理解)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1728

题意:'.'可以走,'*'障碍,给你起点终点,问从起点最多拐k次弯,问能不能到终点。。

开始做的时候,以为,用优先队列拐弯数小的优先,然后每次用队头遍历旁边的4个点。。。。结果WA了。。。而且还用东西来处理是否拐弯。。。

用BFS来处理最优解问题要用队头来遍历完所有最优解并且进队,再重复。。。而上面WA的原因是,我只把相邻的4个点进了队,而在同行,同列还有最优解没进队,导致那些之前没进队的,进队的时候就已经不是最优解了。。。。

这题要用队头遍历4个方向(而不是4个点)。。。每步都是最优,所以最后也是最优。。。。

vis[][]是该点有没遍历过,遍历过的就已经最优了。。。即,队列里的都已经最优了,也就是队头也是最优的。。。。

要特别注意代码标成//********的地方

对比正确和错误代码的图:

错误代码是while(里有!vis[][])而下面没有vis[][];

但是,如果左边那竖的二变成三的时候,那3个'.'就每人遍历了,所以代码是队头遍历同行同列中不出界且!='*'的

点,跳过标记过的(已经最优了),将未标记的点入队。。。

还有我的q1.turn_num = -1初始化为-1(为了把起点同行同列拐弯数是0,所以如果题目起点等于终点的话,最少拐弯数就成了-1)。。。。其实如果题目改成求最少拐弯数的话,就稍微判断一下是不是起点等于终点。。。。

代码:

#include <iostream>
#include <queue>
using namespace std;

const int M = 111;

int n, m;
int max_turn;
int star_x, star_y, end_x, end_y;
char g[M][M];
bool vis[M][M];
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
//右,下,左,上


struct Node
{
    int x, y;
    int turn_num;

};

int Bfs()
{
    queue <Node> q;
    Node q1;
    q1.x = star_x;
    q1.y = star_y;
    q1.turn_num = -1;
    q.push(q1);
    vis[star_x][star_y] = 1;

    while (!q.empty())
    {
        Node q2 = q.front();
        q.pop();

        if (q2.x == end_x && q2.y == end_y && q2.turn_num <= max_turn)
        {
            return 1;
        }

        q1.turn_num = q2.turn_num + 1;
        
        for (int i = 0; i < 4; i++)
        {
            q1.x = q2.x + dir[i][0];
            q1.y = q2.y + dir[i][1];
            while (q1.x >= 1 && q1.x <= n && q1.y >= 1 && q1.y <= m && g[q1.x][q1.y] == '.'/* && !vis[q1.x][q1.y]*/)//**********
            {
                if (!vis[q1.x][q1.y])//*********************************
                {
                q.push(q1);
                vis[q1.x][q1.y] = 1;
                }
                q1.x += dir[i][0];
                q1.y += dir[i][1];
            }
        }
    
    }
    return 0;
}

int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= m; j++)
            {
                scanf(" %c", &g[i][j]);
            }
        }

        scanf("%d%d%d%d%d", &max_turn, &star_y, &star_x, &end_y, &end_x);

        memset(vis, 0, sizeof(vis));



        if (Bfs())
        {
            puts("yes");
        }
        else
        {
            puts("no");
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/qiufeihai/p/2659159.html