浏览器标题切换
浏览器标题切换end

FZU2150 - Fire Game - 双起点BFS

题意:

给出\(T\)组数据,每组数据给出\(N\)\(M\),表示接下去\(N\)\(M\)列。
图中“#”代表草,可以点燃;“.”点代表不能点燃;“#”和“.”都以走。
现在需要同时点两把火(位置可以重合),火的燃烧方向是上下左右,可以同时进行(注意!:不是一次只能一个方向,可以同时上下左右)。
若能烧完所有草(#),则输出最少时间,否则输出-1。

思路:

首先需要特判,如果草#的个数小于等于2的话,直接输出零(因为意味着点火的地方直接着了,无需耗费时间)。
否则,
因为是同时点燃两把火,所以相当于是双起点的BFS。
所以,我们先把草#用结构体存储起来,然后双for循环让每个草之间去进行一个BFS比较最短时间。
在BFS判断的时候,可以先让两个起点都入队,然后就是正常的BFS写法。

AC代码:

#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<list>
#include<stdlib.h>
#include<map>
#include<stack>
#include<stdio.h>
#include<queue>
using namespace std;
typedef long long ll;
#define sc(T) scanf("%d",&T)
#define scc(x,y) scanf("%d %d",&x,&y)
#define pr(T) printf("%d\n",T)
#define f(a,b,c) for (int a=b;a<=c;a++)
#define ff(a,b,c) for (int a=b;a>=c;a--)
#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
#define eps 1e-9
#define PI acos(-1)

int n,m,p;
char a[12][12];
bool book[12][12];
int to[4][2]={{1, 0},{-1,0},{0, 1},{0, -1}};
//int to[4][2]={0,1,1,0,-1,0,0,-1};
struct node
{
    int x,y,ss;
}e[110],pp,qq;

int bfs(node x,node y)
{
    //book[x.x][x.y]=book[y.x][y.y]=1;
    queue<node> Q;
    x.ss=0,y.ss=0;
    Q.push(x),Q.push(y);
    book[x.x][x.y]=1;
    book[y.x][y.y]=1;
    // int ans=0;
    int cnt=2;
    while(!Q.empty())
    {
        pp=Q.front();
        Q.pop();
        //   ans=pp.ss;
        for(int i=0;i<4;i++)
        {
            qq=pp;
            qq.x+=to[i][0];
            qq.y+=to[i][1];
            qq.ss+=1;
            if(qq.x>=0&&qq.x<n&&qq.y>=0&&qq.y<m&&!book[qq.x][qq.y]&&a[qq.x][qq.y]!='.') //先判边界防止越界,或者单独写一个judge函数
            {
                book[qq.x][qq.y]=1;
                cnt++;
                Q.push(qq);
                if(cnt==p) // 说明所有数量的草#(数量为p)已经全部点燃了
                    return qq.ss; // 返回最小步数,也就是最短时间。
            }
        }
    }
    // return ans;
    return inf;
}

int main()
{
    int T,cas=1;
    sc(T);
    while(T--)
    {
        scc(n,m);
        p=0;
        for(int i=0;i<n;i++)
        {
            scanf("%s",a[i]);
            for(int j=0;j<m;j++)
            {
                if(a[i][j]=='#')// # grass
                {
                    e[p].x=i;
                    e[p++].y=j;
                }
            }
        }
        if(p<=2)//特判 最多只有两个# 别忘了输出      不特判的话WA
        {
            printf("Case %d: 0\n",cas++);
            continue;
        }
        int mi=inf;
        for(int i=0;i<p;i++)
        {
            for(int j=i+1;j<p;j++)//0 save time
            {
                mem(book,0);
                int w=bfs(e[i],e[j]);
                mi=min(w,mi);
            }
        }
        if(mi==inf)
            printf("Case %d: -1\n",cas++);
        else
            printf("Case %d: %d\n",cas++,mi);
    }
    return 0;
}
posted @ 2020-07-26 09:50  抓水母的派大星  阅读(132)  评论(0编辑  收藏  举报