一开始看上去认为是个bfs水题,然后发现有点坑。
最后总结是:一道有点坑的水题。
a:天使
x:守卫
r:天使的friend
# :墙
. :路
题意:天使关在有守卫的牢中,他的朋友们(Angel's friends)去救他,意味着有多个r。
从a开始,走到最近的朋友结束。
刚开始的时候没注意是多个friends,普通的队列做bfs只能得到步数最少的解法,而不是时间最少的。
该题可以用优先队列。
好,下面就来个不用优先队列的代码↖(^ω^)↗。
#include <iostream>
#include <stdio.h>
#include <queue>
#define max 0xffffff
using namespace std;
int m,n;
char maze[205][205]; //迷宫
int step[205][205]; //到每一点的步数
int dirx[]={0,1,0,-1},diry[]={1,0,-1,0}; //四方向
typedef struct ac //记录坐标 已用时间
{
int x,y;
int d;
}seat;
inline int fmin(int a,int b)
{
return a<b?a:b;
}
void bfs(seat w)
{
queue<seat> q;
q.push(w);
step[w.x][w.y]=0;
while(!q.empty())
{
w=q.front();
q.pop();
// if(maze[w.x][w.y]=='r')<span style="white-space:pre"> </span>有这个判断就只能得到步数最优而不是时间最优
// return ;
for(int i=0;i<4;i++)
{
seat f=w;
f.d++;
f.x+=dirx[i];
f.y+=diry[i];
if(f.x<0 || f.x>=n || f.y<0 || f.y>=m || maze[f.x][f.y]=='#')
continue;
if(maze[f.x][f.y]=='x')
f.d++;
if(step[f.x][f.y]<=f.d)
continue;
step[f.x][f.y]=f.d;
q.push(f);
}
}
}
void disp()
{
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
if(step[i][j]<1000)
printf("%5d",step[i][j]);
else
printf("%5d",-1);
printf("\n");
}
}
int main()
{
while(cin>>n>>m)
{
seat start,end[205]; //a 起点,r 多个终点
int k=0;
for(int i=0;i<n;i++)
{
cin>>maze[i];
for(int j=0;j<m;j++)
{
step[i][j]=max; //每一步时间初始化
if(maze[i][j]=='a')
start.x=i,start.y=j,start.d=0; //起点时间为0
else if(maze[i][j]=='r')
end[++k].x=i,end[k].y=j;
}
}
bfs(start);
int w=max;
for(int i=1;i<=k;i++)<span style="white-space:pre"> </span>//end记录了所有r的位置,找时间最优解
w=fmin(w,step[end[i].x][end[i].y]);
if(w==max)
cout<<"Poor ANGEL has to stay in the prison all his life."<<endl;
else
cout<<w<<endl;
}
return 0;
}