【J - Fire!】

80 篇文章 0 订阅
80 篇文章 0 订阅

思路:

  • 自己想出来豆
  • BFS
  • 使用两个列表分别记录火的状态和人的状态,先火再人,并且使用火的新状态来对人剪枝。

代码:

  • 210ms
//210ms


#include <iostream>
#include <cstring>
#include <queue>

using namespace std;

const int maxn = 1005;
const int moveto[4][2] = {1,0 , -1,0 , 0,1 , 0,-1};

int M,N;
int ans;
char mp [maxn][maxn];
bool vis[maxn][maxn];
struct Joe{
	int x , y;
	int step;
	Joe(int x,int y,int step) : x(x) , y(y) , step(step) {} ;
};
struct Fire{
	int x,y;
	Fire(int x,int y) : x(x) , y(y) {} ;
};
queue<Joe>  Qj;
queue<Fire> Qf;

void init(){
	ans = 0;
	memset(vis , false , sizeof(vis));
	while(Qj.size())
		Qj.pop();
	while(Qf.size())
		Qf.pop();
	return ;
}

void bfs(){
	while(Qj.size()){
		int fnum = Qf.size();
		int jnum = Qj.size();
		for(int i=1;i<=fnum;i++){
			Fire cur = Qf.front();Qf.pop();
			int x = cur.x;
			int y = cur.y;
			for(int i=0;i<4;i++){
				int nx = x + moveto[i][0];
				int ny = y + moveto[i][1];
				if(vis[nx][ny])
					continue;
				if(nx < 1 || nx > M || ny < 1 || ny > N)
					continue;
				vis[nx][ny] = true;
				Qf.push(Fire(nx,ny));
			}
		}
		for(int i=1;i<=jnum;i++){
			Joe cur = Qj.front();Qj.pop();
			int x = cur.x , y = cur.y ;
			for(int i=0;i<4;i++){
				int nx = x + moveto[i][0];
				int ny = y + moveto[i][1];
				if(vis[nx][ny])
					continue;
				vis[nx][ny] = true;
				Qj.push(Joe(nx , ny , cur.step + 1));
				if(nx < 1 || nx > M || ny < 1 || ny > N){
					ans = cur.step + 1;
					return ;
				}
			}
		}
	}
	return ;
}

int main(){
	int T;cin>>T;
	while(T--){
		init();
		cin>>M>>N;
		for(int i=1;i<=M;i++)
			for(int j=1;j<=N;j++){
				cin>>mp[i][j];
				if(mp[i][j] == '#')
					vis[i][j] = true;
				if(mp[i][j] == 'J')
					Qj.push(Joe(i,j,0)) , vis[i][j] = true;
				if(mp[i][j] == 'F')
					Qf.push(Fire(i,j))  , vis[i][j] = true;
			}
		bfs();
		if(ans)
			cout<<ans<<endl;
		else
			cout<<"IMPOSSIBLE"<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值