洪水

【题目描述】

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;
}
posted @ 2016-04-30 10:12  前前前世。  阅读(222)  评论(0编辑  收藏  举报