两点搜索 FZU - 2150 Fire Game 两点BFS
题意:
在一个木板上有许多方格,每一个方格里面放有不同的东西,一种是草用‘#’表示另一种是‘.’表示什么都没有,有两个人可以分别去点燃其中的一个方格里的草,然后每隔一分钟火势会蔓延到与他相邻的上下左右四个格。‘.’的地方火势不可以蔓延过去。
如果可以将里面的草全部烧完,要求解最小的时间是多少
否则 输出 -1;
思路:
最多只可以点两次火,所以如果草的堆数超过2则肯定不可以。
其余就是要求解符合规定时所用的最短时间。
1.用深搜判断是否符合只有小于等于两堆草的规定,不符合直接输出-1;
2.如果符合,则分两种情况 是一堆还是两堆(其实也没有必要分,但是代码是按分开写的,有兴趣自己可以尝试不分开的写法)分别用广搜求出最短时间即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<cmath>
using namespace std;
struct node{
int xx,yy;
};
char mapp[15][15];
char map1[15][15];
int dist[15][15];
int vis[15][15];
int go[8]={1,0,-1,0,0,1,0,-1};
queue<node>qq[105]; //将可以点火的的节点放进队列,暴力枚举即可得到答案
void dfs(int x,int y,int nn,int mm,int cc){
node temp;
temp.xx=x;temp.yy=y;
qq[cc].push(temp);
map1[x][y]='.';
for(int i=0;i<8;i+=2){
int xx=x+go[i];
int yy=y+go[i+1];
if(map1[xx][yy]=='#'&&xx>=1&&xx<=nn&&yy>=1&&yy<=mm){
dfs(xx,yy,nn,mm,cc);
}
}
return ;
}
int bfs(int x,int y,int nn,int mm){ //普通广搜
int maxx=-1;
memset(dist,0,sizeof(dist));
memset(vis,0,sizeof(vis));
node now,temp;
now.xx=x;now.yy=y;
queue<node>q;
//cout<<q.size()<<endl;
q.push(now);
dist[now.xx][now.yy]=0;
vis[now.xx][now.yy]=1;
while(!q.empty()){
now=q.front();
q.pop();
for(int i=0;i<8;i+=2){
temp.xx=now.xx+go[i];
temp.yy=now.yy+go[i+1];
//cout<<map1[temp.xx][temp.yy]<<endl;
if(!vis[temp.xx][temp.yy]&&temp.xx>=1&&temp.xx<=nn&&temp.yy>=1&&temp.yy<=mm&&map1[temp.xx][temp.yy]=='#'){
dist[temp.xx][temp.yy]=dist[now.xx][now.yy]+1;
if(maxx<=dist[temp.xx][temp.yy]){
maxx=dist[temp.xx][temp.yy];
}
q.push(temp);
vis[temp.xx][temp.yy]=1;
}
}
}
return maxx;
}
int bfs_tp(node a,node b,int nn,int mm){ //两点广搜,其实没什么区别,只需要一次性加入两个点就好了
memset(vis,0,sizeof(vis));
memset(dist,0,sizeof(dist));
int maxx=-1;
queue<node>q;
while(!q.empty())
q.pop();
q.push(a);
q.push(b);
vis[a.xx][a.yy]=1;
vis[b.xx][b.yy]=1;
while(!q.empty()){
node now,temp;
now=q.front();
q.pop();
for(int i=0;i<8;i+=2){
temp.xx=now.xx+go[i];
temp.yy=now.yy+go[i+1];
if(!vis[temp.xx][temp.yy]&&temp.xx>=1&&temp.yy>=1&&temp.xx<=nn&&temp.yy<=mm&&map1[temp.xx][temp.yy]=='#'){
dist[temp.xx][temp.yy]=dist[now.xx][now.yy]+1;
maxx=max(maxx,dist[temp.xx][temp.yy]);
q.push(temp);
vis[temp.xx][temp.yy]=1;
}
}
}
return maxx;
}
int main()
{
int t,cnt=0;
int n,m;
scanf("%d",&t);
while(t--){
int c=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%s",mapp[i]+1);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
map1[i][j]=mapp[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(map1[i][j]=='#'){
c++;
dfs(i,j,n,m,c);
}
}
}
//cout<<c<<endl;
if(c>2){
printf("Case %d: -1\n",++cnt);
}
else{
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
map1[i][j]=mapp[i][j];
}
}
int ans1=0x3f3f3f,ans2=0x3f3f3f,ans=0x3f3f3f;
if(c==2){
while(!qq[1].empty()){
node temp;
temp=qq[1].front();
ans1=min(ans1,bfs(temp.xx,temp.yy,n,m));
qq[1].pop();
}
//cout<<endl;
//cout<<qq[2].size()<<endl;
while(!qq[2].empty()){
node temp;
temp=qq[2].front();
ans2=min(ans2,bfs(temp.xx,temp.yy,n,m));
qq[2].pop();
}
//cout<<ans1<<" "<<ans2<<endl;
ans=max(ans1,ans2);
if(ans==-1)ans=0;
}
if(c==1){
node tp[105];int kk=0;
while(!qq[1].empty()){
tp[++kk]=qq[1].front();
qq[1].pop();
}
for(int i=1;i<=kk;i++){
for(int j=1;j<=kk;j++){
ans=min(ans,bfs_tp(tp[i],tp[j],n,m));
//cout<<ans<<endl;
}
}
if(ans==-1)ans=0;
}
if(c==0){
ans=0;
}
printf("Case %d: %d\n",++cnt,ans);
}
for(int i=0;i<105;i++){
while(!qq[i].empty()){
qq[i].pop();
}
}
}
return 0;
}
//其余代码中的细节问题希望大家可以自己琢磨。