大雨应经下了几天雨,却还是没有停的样子。土豪CCY刚从外地赚完1e元回来,知道不久除了自己别墅,其他的地方都将会被洪水淹没。
CCY所在的城市可以用一个N*M(N,M<=50)的地图表示,地图上有五种符号:“. * X D S”。其中“X”表示石头,水和人都不能从上面经过。“.”表示平原,CCY和洪水都可以经过。“*”表示洪水开始地方(可能有多个地方开始发生洪水)。“D”表示CCY的别墅。“S”表示CCY现在的位置。
CCY每分钟可以向相邻位置移动,而洪水将会在CCY移动之后把相邻的没有的土地淹没(从已淹没的土地)。
求CCY回到别墅的最少时间。如果聪哥回不了家,就很可能会被淹死,那么他就要膜拜黄金大神涨RP来呼叫直升飞机,所以输出“ORZ hzwer!!!”。
输入文件 sliker.in
输出文件 sliker.out
Input
3 3
D.*
…
.S.
Output
3
Input
3 3
D.*
…
..S
Output
ORZ hzwer!!!
Input
3 6
D…*.
.X.X..
….S.
Output
6
代碼實現:
人和水都是四方向移動。別墅的效果等於石頭,都可以攔截洪水。
#include<cstdio>
#include<iostream>
using namespace std;
int n,m,qsl,qrl,zh,zl,a,b,c,nh,nl;
int qs[][][],qr[][][];//qs存洪水的啟發點,qr存人的。
int hb[]={,,,-},lb[]={,-,,};//洪水和人的四方向移動。
bool map[][],rj[][];//map標記的點,洪水不能走,人也不能走。rj(路徑)標記的點,人不能走。
char ch;
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++){
cin>>ch;
if(ch=='X') map[i][j]=;
if(ch=='*'){qs[][qsl][]=i;qs[][qsl++][]=j;map[i][j]=;}
if(ch=='S'){qr[][qrl][]=i;qr[][qrl++][]=j;rj[i][j]=;}
if(ch=='D'){zh=i;zl=j;map[i][j]=;}
}
for(int ans=;;ans++){
if(!qrl) break;
b=(ans+)%;c=ans%;//因為洪水和人的啟發點要各用兩個隊列存。
for(int i=;i<qsl;i++){//雖然說是人先走,但走到一個會在離開前會被洪水淹沒的地方有什麼用。
for(int j=;j<;j++){
nh=qs[b][i][]+hb[j];nl=qs[b][i][]+lb[j];
if(!map[nh][nl]&&nh>&&nh<=n&&nl>&&nl<=m){
map[nh][nl]=;
qs[c][a][]=nh;qs[c][a++][]=nl;//存入洪水的隊列。
}
}
}
qsl=a;a=;//qsl存的是洪水的啟發點個數。
for(int i=;i<qrl;i++){
for(int j=;j<;j++){
nh=qr[b][i][]+hb[j];nl=qr[b][i][]+lb[j];
if(nh==zh&&nl==zl){printf("%d\n",ans);return ;}//要在外面,因為別墅約等於石頭。
if(!rj[nh][nl]&&!map[nh][nl]&&nh>&&nh<=n&&nl>&&nl<=m){//有洪水,石頭,別墅(霧)和之前走過的地方不能走了。
rj[nh][nl]=;
qr[c][a][]=nh;qr[c][a++][]=nl;//存入人的隊列。
}
}
}
qrl=a;a=;//qrl存的是人的啟發點個數。
}
printf("ORZ hzwer!!!\n");
return ;
}
這道題有數據坑,不按描述的來,得了90~