0
点赞
收藏
分享

微信扫一扫

H - Fire Game(玩火游戏)——多源点bfs搜索

Fire Game

H - Fire Game(玩火游戏)——多源点bfs搜索_bfs

题意:两小儿在平地上有草的地方点火,火向方蔓延,问平地能否烧完,若能,输出最少时间,否则输出-1.

解题思路:针对确定好了的点火位置,我们可能会有两个源点(即两小儿点火位置不同,即多源点),我们则要从这两个点开始bfs,又因为这两个是相互关联的,所以我们没必要进行两趟bfs搜索,而是将这两个点入队即可,同样设置辅助数组来判断某个状态点是否访问,同时,利用结构体来实现坐标与当前状态消耗时间的关系。由于我们是要判断是否烧完,所以我们要进行烧完的格子数统计,再与平地上有草的格子数进行比较,若烧完,则有解。这里对于点火位置我们是不知道的,即我们得枚举所有的点火方案,再逐一比对进行判断得出最小值,利用无穷大表示无解
AC代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<stack>
#include<queue>
#include<cstring>
#include<memory.h>
#include<map>
#include<iterator>
#include<list>
#include<set>
#include<functional>

using namespace std;

const int maxn=11;//最大长和宽
char graph[maxn][maxn];//表示平地
int t,n,m;//t组测试用例,n*m代表平地的大小
bool visited[maxn][maxn];//辅助数组,判断该点是否被访问过
int go[4][2]={{1,0},{-1,0},{0,1},{0,-1}};//火的四个行动路径,记住是同时蔓延。
const int INF=0x3f3f3f3f;//表示无穷大。
int sum;//可以燃烧的点数。
typedef struct node
{
int x,y;//当前状态火的坐标
int time;//表示烧到当前状态所用时间
}node;
bool check(int x,int y){//检查函数,判断该点是否可行
if(x<0||x>=n||y<0||y>=m)//出界了
return false;
else if(graph[x][y]!='#'){//说明该点不是草地,无法燃烧
return false;
}
else if(visited[x][y]){
//如果被访问过
return false;
}
return true;
}
int bfs(int X1,int Y1,int X2,int Y2){
queue<node> Q;
node t1,t2;
memset(visited,false,sizeof(visited));//初始化辅助数组。
int num=0;//代表已被烧的火的个数。
int maxx=0;//用于存储燃烧完所消耗时间的最大值
t1.x=X1;t1.y=Y1;t1.time=0;//保存坐标,初始化起始点。
t2.x=X2;t2.y=Y2;t2.time=0;
if(t1.x==t2.x&&t1.y==t2.y){
num=1;//说明起始源点为同一个点。
Q.push(t1);
}
else{
num=2;//说明不同,则两源点同时入队
Q.push(t1);
Q.push(t2);
}
//置标志为已访问
visited[X1][Y1]=true;
visited[X2][Y2]=true;
//因为都已入队,接下来我们利用t1和t2来实现我们的bfs搜索
while(!Q.empty()){
t1=Q.front();//取队头元素
Q.pop();
for(int i=0;i<4;i++){
t2.x=t1.x+go[i][0];
t2.y=t1.y+go[i][1];
if(check(t2.x,t2.y)){
//说明符合条件
num++;//被燃烧的点+1;
t2.time=t1.time+1;
if(t2.time>maxx){
maxx=t2.time;
}
visited[t2.x][t2.y]=true;
Q.push(t2);
}
}
}
if(num<sum){
return INF;//没有烧完,返回
}
else
return maxx;//这场路径的最后消耗的时间。
}
int main(){
while(cin>>t){
for(int i=1;i<=t;i++){
int result=INF;
int maxx;//接收bfs返回的结果
sum=0;
cin>>n>>m;
getchar();//回收换行符
for(int i1=0;i1<n;i1++){
for(int j1=0;j1<m;j1++){
scanf("%c",&graph[i1][j1]);
if(graph[i1][j1]=='#')
sum++;//得出应该燃烧的格子数目。
}
getchar();//回收换行符
}
//接下来开始判断所有结果,找出最小值。
for(int i1=0;i1<n;i1++){
for(int j1=0;j1<m;j1++){
if(graph[i1][j1]=='#'){
//开始寻找下一个点。
for(int i2=i1;i2<n;i2++){
for(int j2=0;j2<m;j2++){
if(i1!=i2||j2>=j1){
if(graph[i2][j2]=='#'){
//已找到,开始bfs搜索
maxx=bfs(i1,j1,i2,j2);
result=min(result,maxx);
}
}
}
}
}
}
}
if(result==INF){
cout<<"Case "<<i<<": -1"<<endl;
}
else{
cout<<"Case "<<i<<": "<<result<<endl;
}
}
}
return 0;
}


举报

相关推荐

0 条评论