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

本文介绍了一个关于BFS广搜算法的应用实例,通过解决一个特定的问题,详细讲解了如何利用优先队列来优化搜索过程,并实现最短路径的同时记录路径细节。文章还提供了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雪的期许

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值