UVa 11624 Fire!(BFS)

这是一道比较基础的BFS的题目。和其他题目不同的是,这道题需要初始化一下每个格子起火的时间。

这几天参加比赛,发现,算法死套模板真的不对,要灵活运用,发挥自己智慧的大脑,才能有更优秀的算法的应用!

还有,分析问题的能力也真的很重要,一道题目可能说得很长,但是最有用的只有那么几句话,从那几句话中再提炼出来一些实质性的东西,就是解题的思路了!

想这道题,实际上就是两次求最短路径,第一次求最短路径,限制第二次求最短路径!还有一个思想就是超级源,这是一个比较比片的思想在解题的过程中,网络会用得比较多。

这里就是将开始时间,所有起火的点都放入队列,并且最短路径设为了0,相当于将它们都视为起点

具体代码如下:

#include <cstdio>
#include <vector>
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 1010;
const int INF = 100000;
int T, n, m, ans;
int tim[N][N], d[N][N];
int a[4] = { 0, 0, 1, -1 }, b[4] = { 1, -1, 0, 0 };
char g[N][N];
queue <pair<int, int> > q;
pair<int,int> S, u, tmp;

void initTime() {
    while ( !q.empty() ) {
        u = q.front(); q.pop(); 
        int ux = u.first, uy = u.second;
        for ( int i = 0; i < 4; ++i ) {
            int x = ux + a[i], y = uy + b[i];
            if ( tim[x][y] > tim[ux][uy] + 1 && g[x][y] != '#' ) {
                tim[x][y] = tim[ux][uy] + 1;
                tmp.first = x, tmp.second = y;
                q.push( tmp );
            }
        }
    }
}
void Bfs() {
    d[S.first][S.second] = 0;
    queue<pair<int, int> > Q;
    Q.push( S ); ans = INF;
    while ( !Q.empty() ) {
        u = Q.front(); Q.pop();
        int ux = u.first, uy = u.second;
        //cout << ux << ' ' << uy << endl;
        if ( ux == 1 || ux == n || uy == 1 || uy == m ) {
            ans = d[ux][uy];
            break;
        }
        for ( int i = 0; i < 4; ++i ) {
            int x = ux + a[i], y = uy + b[i];
            if ( g[x][y] == '.' && d[x][y] > d[ux][uy] + 1 && d[ux][uy] + 1 < tim[x][y] ) {
                d[x][y] = d[ux][uy] + 1;
              //cout << d[x][y] << ' ' << time[x][y] << "zuobiao   " << x << ' ' << y << endl;
                tmp.first = x, tmp.second = y;
                Q.push(tmp);
            }
        }
    }
}
        
int main()
{
    scanf("%d", &T);
    while ( T-- ) {
        while ( !q.empty() ) q.pop();
        scanf("%d%d", &n, &m); getchar();
        for ( int i = 0; i <= n+1; ++i ) g[i][0] = g[i][m+1] = '#';
        for ( int j = 0; j <= m+1; ++j ) g[0][j] = g[n+1][j] = '#';
        for ( int i = 0; i <= n; ++i ) for ( int j = 0; j <= m; ++j ) tim[i][j] = d[i][j] = INF;
        for ( int i = 1; i <= n; ++i, getchar() ) 
            for ( int j = 1; j <= m; ++j ) {
                scanf("%c", &g[i][j]);
                if ( g[i][j] == 'F' ) {
                    tmp.first = i, tmp.second = j;
                    tim[i][j] = 0;
                    q.push(tmp);
                }
                else if ( g[i][j] == 'J' ) S.first = i, S.second = j;
            }
        initTime();
        //for ( int i = 1; i <= n; ++i, cout << endl ) for ( int j = 1; j <= m; ++j ) cout << time[i][j] << " ";
        Bfs();
        //for ( int i = 1; i <= n; ++i, cout << endl ) for ( int j = 1; j <= m; ++j ) cout << d[i][j] << " ";
        if ( ans == INF ) printf("IMPOSSIBLE\n");
        else printf("%d\n", ans+1);
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值