关于广搜的学习

/**
在学习图论的过程中感觉求最短路算是比较简单的题了,直接广搜就可以了
但是很多时候不会这么简单,BFS算法求出来的最优解一般是步数最少的解,
但是步数最少有时并不是最优解,比如图具有权值的时候,要求权值最小,或
要求权值最大,亦或者下面这个有路障的题,简单的求出步数最小并不是最优解。
**************************************************************************
以下题做个分析:
这个题是有路障的情况下求最少时间到达目标节点的问题,可以用BFS解决,
但是要对该算法做一下改动,首先定义一个结构体用来存放当前位置的状态
记录当前位置的坐标,走过的步数,用掉的时间,需要注意的是,在搜索的过程
中,不能一判断到达目标节点就退出搜索,因为此时求得的仅仅是起点到目标节点
最小步数的几个方案中的最小时间,不一定是最优解;因此需要等到队列为空,此时
方可得出最少时间,或者无法到达目标节点的结论。
*/

#include<stdio.h>
#include<string.h>
#include<queue>
#define INF 1234567
using namespace std;

int n,m;///n*m的图
char a[1000][1000];///图
int dir[4][2]= {{-1,0},{0,1},{1,0},{0,-1}};///对应的四个方向
int mintime[1000][1000];///用于标记到达每一个点最小时间状态
/**
用一个结构体表示到达每个点的状态
*/
typedef struct
{
    int x, y;///点的位置
    int step;///走到当前位置所走的步数
    int time;///走到当前位置所花的时间
} Step;
Step start , End;///用于表示起点,和终点

int BFS()
{
    ///搜索前的准备工作
    queue<Step>q;
    start.step = 0;
    start.time = 0;
    mintime[start.x][start.y] = 0;
    Step node, new_node;
    q.push(start);

    while(!q.empty())
    {
        node = q.front();
        q.pop();
        for(int i = 0; i < 4; i++)///从当前层,一层一层的向外扩充节点,
        {                         ///若无特殊情况,到达每一层的步数和时间都是相等的
            int x = node.x + dir[i][0];
            int y = node.y + dir[i][1];
            if(x>=0 && x<n && y>=0 && y<m && a[x][y] != '#')
            {
                new_node.x = x;
                new_node.y = y;
                new_node.step = node.step + 1;
                new_node.time = node.time + 1;
                if(a[x][y] == 'x')///遇到路障时时间增加
                    new_node.time++;
                ///如果以当前节点到达目标节点所花的时间比之前走到(x,y)所用的时间更少
                ///new_node 进队,否则无需进队
                if(new_node.time < mintime[new_node.x][new_node.y])///判断当前时间是否做过记录,若没有记录下当前时间
                {
                    mintime[new_node.x][new_node.y] = new_node.time;
                    q.push(new_node);
                }
            }
        }
    }
    return mintime[End.x][End.y];
}

int main()
{
    while(~scanf("%d%d%d",&n,&m)&&(n+m))
    {
        memset(a,0,sizeof(a));
        for(int i = 0; i < n; i++)
        {
            scanf("%s",a[i]);
            for(int j = 0; j < m; j++)
            {
                if(a[i][j] == 'r')
                {
                    start.x = i;
                    start.y = j;
                }
                else if(a[i][j] == 'a')
                {
                    End.x = i;
                    End.y = j;
                }
            }
        }
        for(int i = 0; i <= n; i++)
            for(int j = 0; j <=m; j++)
                mintime[i][j] = INF;

        int mint = BFS();

        if(mint < INF)
            printf("%d\n",mint);
        else
            printf("no come");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值