原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1242
题意:angel被抓了,他的朋友们(可能不止一个)——用r表示,要去救他,路上有x表示守卫。上下左右移动要花一单位时间,杀死守卫也要花一个单位时间。问最少花多少时间才能救到angel。
思路:由于有守卫,走带有守卫的路会花2时间。对于这用优先队列,优先走时间少的。还有一个坑点就是 r 可能有很多个,正常的从 r 跑bfs就不合适了。这里就要反向跑bfs,即以 a 为起点,找到 r 就结束。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 2e2+10;
int Dir[4][2] = {1,0, 0,1, -1,0, 0,-1};
char Map[N][N];
int vis[N][N];
int n,m;
struct node{
int x,y,step;
bool operator < (const node & a) const {
return a.step < step;
}
} S,Now,Next;
int bfs(){
memset(vis,0,sizeof(vis));
priority_queue<node> q;
S.step = 0;
q.push(S);
while(!q.empty()){
Now = q.top();
q.pop();
if(Map[Now.x][Now.y] == 'r'){
return Now.step;
}
for(int i=0;i<4;i++){
int X = Now.x + Dir[i][0];
int Y = Now.y + Dir[i][1];
if(X >= 0 && X < n && Y >= 0 && Y < m && vis[X][Y] == 0 && Map[X][Y] != '#'){
vis[X][Y] = 1;
Next.x = X,Next.y = Y;
Next.step = Now.step + 1;
if(Map[X][Y] == 'x'){
Next.step += 1;
}
q.push(Next);
}
}
}
return -1;
}
int main(){
while(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] == 'a'){
S.x = i;
S.y = j;
}
}
}
int ans = bfs();
if(ans != -1) printf("%d\n",ans);
else puts("Poor ANGEL has to stay in the prison all his life.");
}
return 0;
}