题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1026
题意,x代表不能走的路,小点 代表可以走的路,数字代表需要在此处停留的步数(时间)。
BFS广搜即可。但这个题有一个值得关注的地方,他需要在数字处停留几步来打怪,那么有一个问题是:步数最少找到出口的方案,会因为打怪而时间(或者说步数)变长,就有可能不在是最短时间。
我们知道bfs广搜是横向搜索一棵树,最先搜到出口的树的那一层,一定是距离最近的走路方案,但这个题会因为打怪而延长时间,因此需要用到优先队列。
(优先队列的定义可以百度)
优先队列的作用是,对树的每一层搜索时,最先搜索当前步数最少的那个方向。
(就是每一次循环去找下一步之前,对队列中的所有元素按时间(步数)排序)。
还有一个难点是输出,本题要求输出路径,不仅仅输出步数(时间)。
这个的处理,我是用了记录前驱的方法,即在每一个点,记录下上一步所在的点,最后再往回退,推到起点。
为了方便记录路径,这个题我没有用STL库的队列,是自己定义的数组代替数列(这样就可以留下每一步的路径,方便记录路径,如果用C++里的queue队列,也未尝不可,记录路径也可以用一个二维数组来记录每一个点的上一步是哪里,从终点往回退)
/*************
代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
struct point{
int last;//记录上一步从哪里来
int x,y; //坐标
int step;//记录当前的步数
int HP;//记录小怪血量(即 需要停留多久)
};
int dir[4][2]={0,1,1,0,-1,0,0,-1};//控制方向。
point path[101010]; //用来代替队列的数组
char map[110][110];
int N,M;
int cmp(point a,point b)//模拟优先队列的功能,(按步数排序)
{
if(a.step<b.step)
return 1;
return 0;
}
int bfs()
{
int front=0;//队列头
int rear=0;//队列尾
point u,v;
u.step=u.HP=u.x=u.y=0;
u.last=-1; //把起点的前驱标记为-1,方便在输出的时候作为结束条件
path[rear++]=u; //加入队尾
map[0][0]='X'; //走过的路标记,以免重复来过
while(front<rear)
{
sort(path+front,path+rear,cmp);//模仿优先队列排序
u=path[front++];//取队头元素
for(int i=0;i<4;i++)
{
v.x=u.x+dir[i][0];
v.y=u.y+dir[i][1];
if(v.x>=0&&v.x<N&&v.y>=0&&v.y<M && map[v.x][v.y]!='X')//可以继续走
{
if(map[v.x][v.y]!='.') //不是‘X’‘‘.’那便是数字
v.HP=map[v.x][v.y]-'0';//注意减掉‘0‘,记下怪物血量
else
v.HP=0;
v.step=v.HP+u.step+1; //步数
v.last=front-1; //前驱坐标在队列中的位置 map[v.x][v.y]='X'; //标记走过了
path[rear++]=v; //装进队尾
if(v.x==N-1&&v.y==M-1)//出口
{
return rear-1;
}
}
}
}
return -1;/
void output(int rear)
{
point v=path[rear];
if(v.last==-1) //没有前驱了
{
return;
}
point u=path[v.last];//前驱
output(v.last);
printf("%ds:(%d,%d)->(%d,%d)\n",v.step-v.HP, u.x,u.y, v.x,v.y);
if(v.HP>0) //有野怪
{
for(int i=v.HP;i>0;i--)
{
printf("%ds:FIGHT AT (%d,%d)\n",v.step-i+1,v.x,v.y);
}
}
}
int main()
{
while(~scanf("%d%d",&N,&M))
{
for(int i=0;i<N;i++)
scanf("%s",map[i]);
int v=bfs();
if(v>=0)
{
printf("It takes %d seconds to reach the target position, let me show you the way.\n",path[v].step);
output(v);
}
else
{
puts("God please help our poor hero.");
}
puts("FINISH");
}
return 0;
}