洪水
【题目描述】
CCY所在的城市可以用一个N*M(N,M <= 50)的地图表示,地图上有五种符号:“. * X D S”。其中,“X”表示石头,水和人都不能从上面经过,“.”表示平原,CCY和洪水都可以经过,“*”表示洪水开始的地方(可能有多个地方同时开始发生洪水),“D”表示CCY的别墅,“S”表示CCY现在的位置。
CCY每分钟可以向相邻位置移动,而洪水将会在CCY移动之后把相邻的没有洪水的土地淹没(从已淹没的土地)。
先询问CCY回到别墅的最少时间。
【输入描述】
第一行输入两个整数N和M(N,M <= 50);
接下来输入一个N*M的字符矩阵,表示CCY所在城市的地图。
【输出描述】
输出一个整数,表示CCY回到别墅需要的最少时间,如果无解,输出-1。
【输入样例】
3 3
D.*
...
.S.
【输出样例】
3
【数据范围及提示】
先BFS出每个点被水淹没的时间,然后再次BFS。
源代码: #include<cstdio> #include<cstring> #include<queue> using namespace std; queue <int> Q; int x[4]={0,0,1,-1}; int y[4]={1,-1,0,0}; int m,n,End1,End2,Start1,Start2,i[51][51]; int main() //细节巨多的BFS题,做搜索还得三思而后行。 { memset(i,0x3f,sizeof(i)); scanf("%d%d\n",&n,&m); for (int a=1;a<=n;a++) { char S[51]; scanf("%s",S+1); //看来NOIP字符串输入就靠它了。 for (int b=1;b<=m;b++) { if (S[b]=='D') { End1=a; End2=b; i[a][b]=0; //洪水无法到达的标记。 } if (S[b]=='S') { Start1=a; Start2=b; } if (S[b]=='X') i[a][b]=0; if (S[b]=='*') { i[a][b]=0; Q.push(a); Q.push(b); } } } while (!Q.empty()) { int X=Q.front(); //新奇的队列用法,值得学习。 Q.pop(); int Y=Q.front(); Q.pop(); for (int a=0;a<4;a++) { int t1=X+x[a]; int t2=Y+y[a]; if (!t1||!t2||t1>n||t2>m||i[t1][t2]!=i[0][0]) //不能走的。 continue; i[t1][t2]=i[X][Y]+1; Q.push(t1); Q.push(t2); } } Q.push(0); Q.push(Start1); Q.push(Start2); while (!Q.empty()) { int t=Q.front(); Q.pop(); int X=Q.front(); Q.pop(); int Y=Q.front(); Q.pop(); for (int a=0;a<4;a++) { int t1=X+x[a]; int t2=Y+y[a]; if (t1==End1&&t2==End2) { printf("%d",t+1); return 0; } if (!t1||!t2||t1>n||t2>m||i[t1][t2]<=t+1) //走过了或者洪水早已没过。 continue; i[t1][t2]=0; //先到就是最优,直接标记不能返回。 Q.push(t+1); Q.push(t1); Q.push(t2); } } printf("ORZ hzwer!!!"); return 0; }