优先队列下的bfs————拯救行动

公主被恶人抓走,被关押在牢房的某个地方。牢房用 N \times M (N, M \le 200)N×M(N,M≤200) 的矩阵来表示。矩阵中的每项可以代表道路(@)、墙壁(#)、和守卫(x)。

英勇的骑士(r)决定孤身一人去拯救公主(a)。我们假设拯救成功的表示是 "骑士到达了公主所在的位置"。由于在通往公主所在位置的道路中可能遇到守卫,骑士一旦遇到守卫,必须杀死守卫才能继续前进。

现假设骑士可以向上、下、左、右四个方向移动,每移动一个位置需要 11 个单位时间,杀死一个守卫需要花费额外的 11 个单位时间。同时假设骑士足够强壮,有能力杀死所有的守卫。

给定牢房矩阵,公主、骑士和守卫在矩阵中的位置,请你计算拯救行动成功需要花费最短时间。

输入格式

1、两个整数代表 NN 和 M, (N, M \le 200)M,(N,M≤200).
2、随后 NN 行,每行有 MM 个字符。"@" 代表道路,"a" 代表公主,"r" 代表骑士,"x" 代表守卫, "#" 代表墙壁。

输出格式

如果拯救行动成功,输出一个整数,表示行动的最短时间。
如果不可能成功,输出 "Impossible"。

前言

遇到有条件的,例如这一题,如一直打怪,时间肯定很长,所以我们尽量少打架

这时候就可以用优先队列,在放进队列是会自动排列

输入1

7 8
#@#####@
#@a#@@r@
#@@#x@@@
@@#@@#@#
#@@@##@@
@#@@@@@@
@@@@@@@@
13

输入2

13 40
@x@@##x@#x@x#xxxx##@#x@x@@#x#@#x#@@x@#@x
xx###x@x#@@##xx@@@#@x@@#x@xxx@@#x@#x@@x@
#@x#@x#x#@@##@@x#@xx#xxx@@x##@@@#@x@@x@x
@##x@@@x#xx#@@#xxxx#@@x@x@#@x@@@x@#@#x@#
@#xxxxx##@@x##x@xxx@@#x@x####@@@x#x##@#@
#xxx#@#x##xxxx@@#xx@@@x@xxx#@#xxx@x#####
#x@xxxx#@x@@@@##@x#xx#xxx@#xx#@#####x#@x
xx##@#@x##x##x#@x#@a#xx@##@#@##xx@#@@x@x
x#x#@x@#x#@##@xrx@x#xxxx@##x##xx#@#x@xx@
#x@@#@###x##x@x#@@#@@x@x@@xx@@@@##@@x@@x
x#xx@x###@xxx#@#x#@@###@#@##@x#@x@#@@#@@
#@#x@x#x#x###@x@@xxx####x@x##@x####xx#@x
#x#@x#x######@@#x@#xxxx#xx@@@#xx#x#####@

7




详细代码及解释如下所示

#include<iostream>
#include<queue>
using namespace std;
int n,m;//n表示有几行 m表示有几列 
int x,y,mx,my;//初始位置 目的位置 
char map[300][300];
struct pos 
{
	int x,y;//当前位置 
	int s;//距离出发点的位置 
	friend bool operator <(pos p1,pos p2)
	 {//这里的<为从大到小排列,>为从小到大排列 
	 	return p1.s>p2.s;//这一题要让步数少的先进行 
	 }
}cur,nex;
bool vis[300][300];//标记数组 
priority_queue <pos> q;//创建队列来表示王子可能的位置

bool in(int x,int y)
{//判断是否在范围中 
	return 0<=x&&x<n && 0<=y&&y<m ; 
}

int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};//方向数组 
int bfs (int x ,int y ) 
{//int型表示有返回值
	vis[x][y]=1;
	cur.x=x;
	cur.y=y;
	cur.s=0;//初始数据初始化
	q.push(cur);//把第一个点放进去 
	while(q.size())
	{//队列只要不空就会一直执行 
		cur=q.top();//取出第一个点 
		q.pop();//每次取出后就要把这个点清除
		for(int i=0;i<4;i++)
		{
			nex.x=cur.x+dir[i][0] ;
			nex.y=cur.y+dir[i][1] ;
			if(nex.x==mx && nex.y==my)
			{
				return cur.s+1;//如果找到立马返回,结束查找,
							   //此时找到的数值一定最小 
			}
			else if(in(nex.x,nex.y) && !vis[nex.x][nex.y])
			{//其他的点都会被收入其中,但需要的条件是在范围内,是@,x,未被走过 
				if(  map[nex.x][nex.y]=='@' )//如果是路 
				{
					vis[nex.x][nex.y]=1;//标记走过
					nex.s=cur.s+1;
					q.push(nex); 
				}
				else if(  map[nex.x][nex.y]=='x' )
				{
					vis[nex.x][nex.y]=1;//标记走过
					nex.s=cur.s+2;
					q.push(nex); 
				}
				
			}
		} 
		
	} 
	return -1; //这里是int函数 所以一定要有返回值 
}
int main()
{
	cin>>n>>m;
	for(int i=0;i<n;i++)
	for(int j=0;j<m;j++)
	{
		cin>>map[i][j];
		if(map[i][j]=='r')
		x=i,y=j;
		if(map[i][j]=='a')
		mx=i,my=j;
	}
	int b=bfs(x,y);
	if(b==-1)//根据返回值得到我们想要的结果 
	cout<<"Impossible";
	else 
	cout<<b<<endl;
	return 0;
}

总结

值得注意的是,优先队列只有取队首元素不同。在优先队重载列中是用top,队列中则用的是front

另一个就是重载运算符,需要在定义我们结构体的时候就在其内部定义

friend bool operator

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值