UVA - 11624 Fire!(多源bfs+雙bfs)

題目連接:

  https://vjudge.ppsucxtt.cn/problem/UVA-11624node

大體題意:

  迷宮裏一個或多個位置有火,火沒一秒蔓延到上下左右四個位置,Jor一秒只能上下左右移動一格,求Jor逃出在不趕上或逃出迷宮的最快時間。ios

思路:

  Jor移動的方向用不少中變化,而火只會隨着時間向四個方向蔓延,因此能夠將Jor和火勢蔓延分紅兩個BFS,最關鍵一點就是Jor到達(i,j)點時(i,j)尚未火,因此能夠經過bfs_fire求出每一個位置火到達的時間,只要Jor提早到達便可,由於最開始可能有多個地方有火,因此bfs_fire不是單元BFS而是多元BFS,其實多元BFS也沒什麼深奧的,就是最開始隊列要加入多個時間爲0的起點便可,而BFS_Jor只要知足到達位置時間小於火到達時間便可加入隊列。spa

代碼:

#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
#include <cmath>
#define fastio ios::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL)

using namespace std;

typedef long long ll;
typedef pair<int, int> PII;

const int N = 1010;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
const int mod = 998244353;

struct node
{
    int arrive_T, x, y;
};

int dis[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};

int n, m, ans, out = 0;
int tim[N][N]; //存(i,j)火到達的時間
char a[N][N];  //存輸入圖
bool vis[N][N];

bool check(int i, int j) //判斷邊界條件
{
    if (i >= 1 && i <= n && j >= 1 && j <= m && a[i][j] != '#' && !vis[i][j])
        return true;
    return false;
}

void bfs_fire()
{
    memset(tim, INF, sizeof tim);
    memset(vis, false, sizeof vis);
    queue<node> q;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            if (a[i][j] == 'F')
            {
                vis[i][j] = true, tim[i][j] = 0;
                q.push({0, i, j});
            }
    while (q.size())
    {
        node t = q.front();
        q.pop();
        for (int k = 0; k < 4; k++)
        {
            int i = t.x + dis[k][0], j = t.y + dis[k][1];
            if (check(i, j))
            {
                q.push({t.arrive_T + 1, i, j});
                vis[i][j] = true, tim[i][j] = t.arrive_T + 1;
            }
        }
    }
}

void bfs_Joe()
{
    memset(vis, false, sizeof vis);
    queue<node> q;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
            if (a[i][j] == 'J')
            {
                q.push({0, i, j}), vis[i][j] = true;
                break;
            }
        if (q.size())
            break;
    }
    while (q.size())
    {
        node t = q.front();
        q.pop();
        if (t.x == 1 || t.x == n || t.y == 1 || t.y == m)
        {
            cout << t.arrive_T + 1 << endl;
            out++;
            return;
        }
        for (int k = 0; k < 4; k++)
        {
            int i = t.x + dis[k][0], j = t.y + dis[k][1];
            if (check(i, j) && t.arrive_T + 1 < tim[i][j]) //只要知足到達位置時間小於火到達時間便可加入隊列
            {
                q.push({t.arrive_T + 1, i, j});
                vis[i][j] = true;
            }
        }
    }
}

int main()
{
    fastio;
    int T;
    cin >> T;
    while (T--)
    {
        cin >> n >> m;
        ans = 0, out = 0;
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
                cin >> a[i][j];
        bfs_fire();
        bfs_Joe();
        if (!out)
            cout << "IMPOSSIBLE" << endl;
    }

    return 0;
}
相關文章
相關標籤/搜索