/**
在学习图论的过程中感觉求最短路算是比较简单的题了,直接广搜就可以了
但是很多时候不会这么简单,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;
}
关于广搜的学习
最新推荐文章于 2021-10-19 09:44:15 发布