http://acm.hdu.edu.cn/showproblem.php?pid=1242
题意:天使被关入了恶魔的监狱,他的朋友们要救他出去,根据给出的“地图“求他的朋友们到达他的位置的最短时间,路途中每走一个格子花费1个单位的时间,遇到守卫者需要再花1个单位的时间把他打倒……
思路:因为朋友不止一个,要从每个朋友出发既要储存每个朋友的初始位置,又要进行多次BFS,极其浪费时间。所以,应该从天使出发找朋友。由于这道题有守卫的存在,最短时间不等于最小步数了,所以不可以用队列了,而要使用优先队列。
BFS时,求最短步数可以用队列;如果每一步有权值且不全为1时,则需要使用优先队列。
#include<cstdio>
#include<cstring>
#include<climits>
#include<queue>
using namespace std;
struct node
{
int x,y,cnt;
friend bool operator < (node a,node b)
{
return a.cnt>b.cnt; //小的在前面
}
};
int map[222][222];
int n,m,min=INT_MAX;
int dx[]={-1,1,0,0},dy[]={0,0,-1,1};
struct node begin;
int bfs()
{
int i,x,y;
struct node now,next;
priority_queue <struct node> q;
q.push(begin);
while(!q.empty())
{
now=q.top();
q.pop();
for(i=0;i<4;i++)
{
x=now.x+dx[i];
y=now.y+dy[i];
if(map[x][y]==-1)
return now.cnt+1;
if(x>0&&x<=n&&y>0&&y<=m&&(!map[x][y]||map[x][y]==2))
{
next.x=x;
next.y=y;
next.cnt=!map[x][y]?now.cnt+1:now.cnt+2;
q.push(next);
map[x][y]=1;
}
}
}
return -1;
}
int main()
{
int i,j,ans;
char c;
while(scanf("%d %d",&n,&m)==2)
{
memset(map,0,sizeof(map));
for(i=1;i<=n;i++)
{
getchar();
for(j=1;j<=m;j++)
{
scanf("%c",&c);
if(c=='.')
map[i][j]=0;
else if(c=='#')
map[i][j]=1;
else if(c=='x')
map[i][j]=2;
else if(c=='r')
{
map[i][j]=-1;
}
else if(c=='a')
{
map[i][j]=1;
begin.x=i;begin.y=j;begin.cnt=0;
}
}
}
ans=bfs();
if(ans<0)
printf("Poor ANGEL has to stay in the prison all his life.\n");
else
printf("%d\n",ans);
}
return 0;
}