題目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1242
這道題目我是用BFS+優先隊列做的。聽說只用bfs會超時。
因爲這道題有多個營救者,所以我們從被營救者開始bfs,找到最近的營救者就是最短時間。
先定義一個結構體,存放座標x和y,還有到達當前點(x,y)消耗的時間。
struct node {
int x,y;
int time;
friend bool operator < (const node &a,const node &b){
//時間少的放在隊列前面
return a.time>b.time;
}
};
注意時間少的先出列。
重點講一下bfs的過程,當前格子命名爲now,走過的下一個格子命名爲next,先將起點賦值給now然後入隊。
now.x=x;
now.y=y;
now.time=0;//源點走到源點時間初始爲0
vis[now.x][now.y]=1;
que.push(now);//源點入隊
之後只要隊列不爲空,就取出隊列的頭節點,判斷是否爲終點也就是任意一個r,如果是r,則返回到達當前節點所需時間即:now.time;若不是r,那接下來把now的四個方向全部遍歷一百,如果不是牆就將其加入隊列,並且把當前time更新:next.time=now.time+delta。delta的值遇到x就是2,否則是1。一直循環直到que.top出來的座標代表的是r。
若隊列爲空即找完了全圖都沒找到r,那就返回-1,代表無法解救。
好了貼個代碼:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int n,m;
int vis[202][202];
char map[202][202];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
struct node {
int x,y;
int time;
friend bool operator < (const node &a,const node &b){
//時間少的放在隊列前面
return a.time>b.time;
}
};
int can_go(int x,int y){
if(x>=0&&x<n&&y>=0&&y<m&&map[x][y]!='#'){
return 1;
}
else return 0;
}
int bfs(int x,int y){
int i;
node now,next;
priority_queue<node>que;
memset(vis,0,sizeof(vis));
now.x=x;
now.y=y;
now.time=0;//源點走到源點時間初始爲0
vis[now.x][now.y]=1;
que.push(now);//源點入隊
while(!que.empty()){
now=que.top();
que.pop();
if(map[now.x][now.y]=='r'){
return now.time;
}
for(i=0;i<4;i++){
next.x=now.x+dir[i][0];
next.y=now.y+dir[i][1];
if(can_go(next.x,next.y)&&!vis[next.x][next.y]){
vis[next.x][next.y]=1;
if(map[next.x][next.y]=='x'){
next.time=now.time+2;
}
else {
next.time=now.time+1;
}
que.push(next);
}
}
}
return -1;
}
int main()
{
int ans;
int i,j;
int x,y;
while(scanf("%d%d",&n,&m)!=EOF){
for(i=0;i<n;i++){
scanf("%s",map[i]);
}
for(i=0;i<n;i++)
for(j=0;j<m;j++)
if(map[i][j]=='a'){
x=i;
y=j;
break;
}
ans=bfs(x,y);
if(ans==-1){
printf("Poor ANGEL has to stay in the prison all his life.\n");
}
else {
printf("%d\n",ans);
}
}
return 0;
}