Fire Game

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










