1. 程式人生 > >UVA 11624 (BFS)

UVA 11624 (BFS)

題目:一個平面迷宮中有一個人,迷宮中有些點起火了,火和人每個單位時間只能向相鄰的格子移動,             其中有一些空間被牆壁佔據,問這個人在不背或燒到的情況下,離開迷宮的最快時間。 分析:搜尋。迷宮中的最短路,首先就會想到bfs;並且bfs利用佇列會使狀態空間按時間順序分層。             而火的擴散過程正好符合這個時間的層次。所以我們會想到,利用兩個佇列,一個儲存人的狀態,             一個儲存火的狀態。按照時間順序,先更新火蔓延的節點,再擴充套件人能到達的節點。             通過分析,我們發現這兩個佇列可以合併,只須初始化的時候,按照火節點然後是人的順序入隊即可。            (節點中加入一個是否是火節點的判斷,就可以兩種節點按不同的細節處理) 注意:時間是指走出迷宮的時間,到達邊界後要加1;初始節點的判斷。

程式碼:

#include<bits/stdc++.h>
using namespace std;
const int MAX = 1010;
int m, n;
char mp[MAX][MAX];
int fire[MAX][MAX];     //火
int people[MAX][MAX];   //人
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
queue<pair<int, int> > Q;
void BFS_fire()
{
    memset(fire, -1, sizeof(fire));
    while ( !Q.empty() )
    {
        Q.pop();
    }
    for (int i=0; i<n; i++)
    {
        for (int j=0; j<m; j++)
        {
            if (mp[i][j] == 'F')
            {
                fire[i][j] = 0;
                Q.push(make_pair(i, j));
            }
        }
    }
    while ( !Q.empty() )        //BFS火能燒到的地方,並且記錄時間
    {
        pair<int, int> a;
        a = Q.front();
        Q.pop();
        int x = a.first;
        int y = a.second;
        for (int i=0; i<4; i++)
        {
            int xx = x + dir[i][0];
            int yy = y + dir[i][1];
            if (xx<0 || xx>=n || yy<0 || yy>=m) continue;
            if (fire[xx][yy] != -1) continue;        //被燒過
            if (mp[xx][yy] == '#') continue;       //有牆
            fire[xx][yy] = fire[x][y] + 1;      //記錄時間
            Q.push(make_pair(xx, yy));
        }
    }
}
int BFS_people()
{
    memset(people, -1, sizeof(people));
    while ( !Q.empty() )
    {
        Q.pop();
    }
    for (int i=0; i<n; i++)
    {
        for (int j=0; j<m; j++)
        {
            if (mp[i][j] == 'J')
            {
                Q.push(make_pair(i, j));
                people[i][j] = 0;
            }
        }
    }
    while ( !Q.empty() )
    {
        pair<int, int> a;
        a = Q.front();
        Q.pop();
        int x = a.first;
        int y = a.second;
        if (x==0 || y==0 || x==n-1 || y==m-1)
        {
            return people[x][y]+1;
        }
        for (int i=0; i<4; i++)
        {
            int xx = x + dir[i][0];
            int yy = y + dir[i][1];
            if (xx<0 || xx>=n || yy<0 || yy>=m) continue;
            if (people[xx][yy] != -1) continue;      //已經走過
            if (mp[xx][yy] == '#') continue;           //有牆
            if (fire[xx][yy] != -1 && people[x][y]+1 >= fire[xx][yy]) continue;     //&&  之前是不能被火燒過  之後是到達的時間不能有火
            people[xx][yy] = people[x][y] + 1;      //更新時間
            Q.push(make_pair(xx, yy));
        }
    }
    return -1;
}
int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d %d", &n, &m);
        //getchar();
        for (int i=0; i<n; i++)
        {
            for (int j=0; j<m; j++)
            {
                cin >> mp[i][j];
            }
        }
        BFS_fire();
        int ans = BFS_people();
        if(ans == -1)
        {
            printf("IMPOSSIBLE\n");
        }
        else
        {
            printf("%d\n",ans);
        }
    }
    return 0;
}