公主被恶人抓走,被关押在牢房的某个地方。牢房用 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