HDU杭电1026 Ignatius and the Princess I(迷宫问题bfs)

题目地址: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;
}




    原文作者:迷宫问题
    原文地址: https://blog.csdn.net/winter2121/article/details/62236401
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞