Problem ID:1012 Rescue
簡單題意:給出一個地圖,其中有一個"a",代表angle,若干個"r",代表去營救angle的朋友,"x"標誌敵人,"."標誌可以行進的區域,"#"標誌不可行進的區域。只可直行,不能斜向前進。走向"."耗時1,走向並擊敗"x"耗時2,求能拯救angle所需要的最短時間。如不能拯救,則輸出"Poor
ANGEL has to stay in the prison all his life."
解題思路形成過程:利用BFS,但所有能經過的區域都要搜索一遍(這是重點),因爲"."區域和"x"區域耗時不同。
用一個二維數組記錄能到達每個區域的最短時間。
在遍歷過程中,如果按照某走法將要到達的某區域的所花費的總時間比之前記錄的要大,則不走,從而進行剪枝。
感想:因爲是所有"."和"x"區域都要遍歷一遍,用DFS也可以。一開始沒有考慮到這個條件,WA了一次,還是考慮的不夠細緻。
代碼:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
int cmap[201][201],mark[201][201];
int r1[201],r2[201];
int dir[4][2]={{-1,0},{0,-1},{0,1},{1,0}};
int aim_r,aim_c;
int n,m;
void bfs(int r,int c)
{
queue<int>s;
s.push(r);
s.push(c);
s.push(0);
mark[r][c]=0;
while(!s.empty())
{
int now_r=s.front();
s.pop();
int now_c=s.front();
s.pop();
int now_cnt=s.front();
s.pop();
for(int i=0;i<4;++i){
int temp_r=now_r;
int temp_c=now_c;
int temp_cnt=now_cnt;
temp_r+=dir[i][0];
temp_c+=dir[i][1];
if(cmap[temp_r][temp_c]==3)
temp_cnt+=2;
else
temp_cnt++;
if(temp_r>=0&&temp_r<n&&temp_c>=0&&temp_c<m)
if(cmap[temp_r][temp_c]!=1&&cmap[temp_r][temp_c]!=5)
if(mark[temp_r][temp_c]>temp_cnt||mark[temp_r][temp_c]==-1)//所有"."和"x"區域必須全部搜索一遍.
{
s.push(temp_r);
s.push(temp_c);
s.push(temp_cnt);
mark[temp_r][temp_c]=temp_cnt;
}
}
}
}
int main()
{
// freopen("2.txt","r",stdin);
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(mark,-1,sizeof(mark));
int t=0;
for(int i=0;i<n;++i)
for(int j=0;j<m;++j){
char temp;
cin>>temp;
if(temp=='r'){
cmap[i][j]=1;
r1[t]=i;
r2[t]=j;
++t;
}
else if(temp=='a'){
cmap[i][j]=2;
aim_r=i;
aim_c=j;
}
else if(temp=='x')
cmap[i][j]=3;
else if(temp=='.') //可不寫
cmap[i][j]=4;
else if(temp=='#')
cmap[i][j]=5;
}
for(int i=0;i<t;++i)
bfs(r1[i],r2[i]);
int cmin=mark[aim_r][aim_c];
if(cmin!=-1)
printf("%d\n",cmin);
else
printf("Poor ANGEL has to stay in the prison all his life.\n");
}
}