UVA-11624Fire!(bfs)

传送门.

思路
两个bfs,一个bfs搜火的路径,一个搜人的路径,最后在图的四条边界判断人是否比火先到即可;

注意有一个坑点,就是火不止有一处,所以在火的bfs中我开了全局的队列,在main里push进去火的位置

这个题刚开始用d数组一边记录走的时间,一边记录是否被搜过,然后wa了好多次,最后多开了一个数组来记录是否被搜过才ac QAQ~

相似题目:QWQ

代码

#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
#include <queue>
#include <utility>
#include <stack>
#define me memset 

using namespace std;

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

const int N = 1010;
const int null = 0x3f3f3f3f;

int T;
int r,c;
int jx,jy;
bool st[N][N];
int dj[N][N],df[N][N];
int dx[4] = {0,1,0,-1},dy[4] = {1,0,-1,0};
string s[N];

void bfsj()
{
	me(dj,0x3f,sizeof dj);
	
	dj[jx][jy] = 0;
	
	queue<PII> q;
	q.push({jx,jy});
	st[jx][jy] = true;
	
	while(q.size())
	{
		auto t = q.front();
		q.pop();
		
		for(int i = 0;i < 4;i ++)
		{
			int x = t.first + dx[i];
			int y = t.second + dy[i];
			
			if(x >= 0 && x < r && y >= 0 && y < c && !st[x][y] && s[x][y] != '#')
			{
				q.push({x,y});
				dj[x][y] = dj[t.first][t.second] + 1;
				st[x][y] = true;
			}
		}
	}
}

queue<PII> qe;

void bfsf()
{
	while(qe.size())
	{
		auto t = qe.front();
		qe.pop();
		
		for(int i = 0;i < 4;i ++)
		{
			int x = t.first + dx[i];
			int y = t.second + dy[i];
			
			if(x >= 0 && x < r && y >= 0 && y < c && !st[x][y] && s[x][y] != '#')
			{
				qe.push({x,y});
				df[x][y] = df[t.first][t.second] + 1;
				st[x][y] = true;
			}
		}
	}
}

int main()
{
	cin >> T;
	
	while(T --)
	{
		cin >> r >> c;
		
		me(df,0x3f,sizeof df);
		for(int i = 0;i < r;i ++)
		{
			cin >> s[i];
		//	cout << s[i] << endl;
			for(int j = 0;j < c;j ++)
			{
				if(s[i][j] == 'J') jx = i,jy = j;
				
				if(s[i][j] == 'F')
				{
					df[i][j] = 0;
					st[i][j] = true;
					qe.push({i,j});
				}
			}
		}
		
//		cout << jx << " " << jy << " " << fx << " " << fy << endl;
		bfsf();
		me(st,0,sizeof st);
		bfsj();

		int ans = null;
		int k = 0;
		for(int i = 0;i < c;i ++)
		{
		//	cout << i << " " << ans << endl;
			if(dj[k][i] < df[k][i]) ans = min(ans,dj[k][i]);
		}
		
		for(int i = 0;i < r;i ++)
		{
		//	cout << i << " " << ans << endl;
			if(dj[i][k] < df[i][k]) ans = min(ans,dj[i][k]);
		}
		
		k = r - 1;
		for(int i = 0;i < c;i ++)
		{
		//	cout << i << " " << ans << endl;
			if(dj[k][i] < df[k][i]) ans = min(ans,dj[k][i]);
		}
		
		k = c - 1;
		for(int i = 0;i < r;i ++)
		{
		//	cout << i << " " << ans << endl;
			if(dj[i][k] < df[i][k]) ans = min(ans,dj[i][k]);
		}
		
		if(ans == null) printf("IMPOSSIBLE\n");
		else printf("%d\n",ans + 1);
		
		me(st,0,sizeof st);
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半碗无糖蓝莓冻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值