FZU 2150 Fire Game(双端bfs搜索)

题意:给你块地,有空地,也有草堆,让你选两个草堆进行点火,燃烧的草堆会引燃上下左右的相邻草堆,每一次引燃花费1s时间,问你最少花多长时间把草堆都点着,如果做不到输出-1.

思路:每次枚举两块草坪,两端同时bfs(也就是说一开始加入两个节点到队列当中,和以前的类型一个道理没什么区别),用变量count1计算草坪个数,当count1减小到0时,即找到了本次枚举的解,并在节点node中设置一变量为c记录当前状态草坪个数(用于返回结果的判断)。

AC代码如下:

#include<cstdio>
#include<queue>
#include<vector> 
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=10+2;
struct node{
	int x,y;
	int c;   //当前状态下草坪的剩余数量 
	node(int x=0,int y=0,int c=0):x(x),y(y),c(c){}
}; 
int n,m;
int count1;    //草坪数量 
char g[maxn][maxn];  
int d[maxn][maxn];
int dir[][2]={{0,1},{0,-1},{1,0},{-1,0}};
bool isValid(node &nd){
	return nd.x>=0&&nd.x<n && nd.y>=0&&nd.y<m;
}
int bfs(node &n1,node &n2){
	int t=count1;            //要保证每次枚举草坪的数量不会被改变 
	memset(d,-1,sizeof(d));
	queue<node>q;
	n1.c=--t;
	q.push(n1);
	n2.c=--t;
	q.push(n2);
	d[n1.x][n1.y]=0;
	d[n2.x][n2.y]=0;
	while(!q.empty()){
		node u=q.front();
		q.pop();
		if(!u.c){         //当草坪的数量为零时说明已经燃烧完了 
		return d[u.x][u.y];}
		for(int i=0;i<4;i++){
			node v=node(dir[i][0]+u.x,dir[i][1]+u.y,0);
			if(isValid(v) && d[v.x][v.y]==-1 && g[v.x][v.y]=='#'){
			    v.c=--t;
				q.push(v);
				d[v.x][v.y]=d[u.x][u.y]+1;
			}
		}
	}
	return -1;
}
int main(){
	int T;
	scanf("%d",&T); 
	int flag=0;
	while(T--){
		scanf("%d%d",&n,&m);
		for(int i=0;i<n;i++)scanf("%s",g[i]);
		count1=0;
		vector<node>vec;
		for(int i=0;i<n;i++)
			for(int j=0;j<m;j++)
				if(g[i][j]=='#'){
					vec.push_back(node(i,j,0));
					count1++;
				}
		if(vec.size()>2){	int min1=10000;      //当草坪数量<=2时直接输出0,否则每次枚举两个草坪 
		for(int i=0;i<vec.size();i++){
			for(int j=i+1;j<vec.size();j++){
					int temp=bfs(vec[i],vec[j]);
					if(temp!=-1){
						min1=min(min1,temp);
					}
			}
		}
		if(min1==10000)printf("Case %d: -1\n",++flag);
		else printf("Case %d: %d\n",++flag,min1);
  }else printf("Case %d: 0\n",++flag);
	}
	return 0;
} 


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

柏油

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

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

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

打赏作者

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

抵扣说明:

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

余额充值