Fire! UVA - 11624 搜索

题解

两次BFS,第一次BFS求出火蔓延到每个位置所需的最小时间。
第二次BFS人物尝试上下左右移动,如果移动到当前位置的时间大于等于火蔓延到的时间则当前人会被烧到,方案不可行。

AC代码

#include <stdio.h>
#include <bits/stdc++.h>
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e3 + 10;
int dir[4][2] = { -1, 0, 1, 0, 0, -1, 0, 1 };
char g[N][N];
int f[N][N]; //火蔓延到的时间
bool vis[N][N];
int n, m, sx, sy;

struct node
{
	int x, y, k;
};
void fire()
{
    memset(f, 0x3f, sizeof(f));
    queue<node> q;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            if (g[i][j] == 'F')
                q.push({ i, j, 0 }), f[i][j] = 0;
    while (!q.empty())
    {
		int x = q.front().x, y = q.front().y, k = q.front().k; q.pop();
        ++k;
        for (int i = 0; i < 4; ++i)
        {
			int xx = x + dir[i][0], yy = y + dir[i][1];
			if (xx >= 1 && xx <= n && yy >= 1 && yy <= m && g[xx][yy] == '.' && f[xx][yy] == INF) //火不会到INF
                q.push({ xx, yy, k }), f[xx][yy] = k;
        }
    }
}
int BFS()
{
	memset(vis, 0, sizeof(vis));
	queue<node> q;
	q.push({ sx, sy, 0 });
	vis[sx][sy] = 1;
	while (!q.empty())
	{
		int x = q.front().x, y = q.front().y, k = q.front().k; q.pop();
		++k;
		for (int i = 0; i < 4; ++i)
		{
			int xx = x + dir[i][0], yy = y + dir[i][1];
			if (xx >= 1 && xx <= n && yy >= 1 && yy <= m)
			{
				if (g[xx][yy] == '.' && !vis[xx][yy] && k < f[xx][yy]) //当前时间火还没到
					q.push({ xx, yy, k }), vis[xx][yy] = 1;
			}
			else
				return k;
		}
	}
	return -1;
}
int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int T;
	cin >> T;
	while (T--)
	{
		cin >> n >> m;
		for (int i = 1; i <= n; ++i)
		{
			scanf("%s", g[i] + 1);
			for (int j = 1; j <= m; ++j)
				if (g[i][j] == 'J')
					g[i][j] = '.', sx = i, sy = j;
		}
		fire();
		int res = BFS();
		if (~res)
			cout << res << endl;
		else
			cout << "IMPOSSIBLE" << endl;
	}

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值