Fire Game FZU

来源:互联网 发布:js解压缩 在线 编辑:程序博客网 时间:2024/06/04 18:52

Fat brother and Maze are playing a kind of special (hentai) game on an N*M board (N rows, M columns). At the beginning, each grid of this board is consisting of grass or just empty and then they start to fire all the grass. Firstly they choose two grids which are consisting of grass and set fire. As we all know, the fire can spread among the grass. If the grid (x, y) is firing at time t, the grid which is adjacent to this grid will fire at time t+1 which refers to the grid (x+1, y), (x-1, y), (x, y+1), (x, y-1). This process ends when no new grid get fire. If then all the grid which are consisting of grass is get fired, Fat brother and Maze will stand in the middle of the grid and playing a MORE special (hentai) game. (Maybe it’s the OOXX game which decrypted in the last problem, who knows.)

You can assume that the grass in the board would never burn out and the empty grid would never get fire.

Note that the two grids they choose can be the same.

Input

The first line of the date is an integer T, which is the number of the text cases.

Then T cases follow, each case contains two integers N and M indicate the size of the board. Then goes N line, each line with M character shows the board. “#” Indicates the grass. You can assume that there is at least one grid which is consisting of grass in the board.

1 <= T <=100, 1 <= n <=10, 1 <= m <=10

Output

For each case, output the case number first, if they can play the MORE special (hentai) game (fire all the grass), output the minimal time they need to wait after they set fire, otherwise just output -1. See the sample input and output for more details.

Sample Input
43 3.#.###.#.3 3.#.#.#.#.3 3...#.#...3 3###..##.#
Sample Output
Case 1: 1Case 2: -1Case 3: 0Case 4: 2

题意:给你一块n*m的地方,上面有草坪和空地,#表示草坪, 先从中任选两块草坪开始烧,火势每过一秒会向上下左右四个方向蔓延,问烧完所有草坪的最小时间。输入保证最小存在一块草坪。


分析:

当只有一块草坪时,直接输出0就好(WA了一次,忘了这一点了)。 两个难点。第一个难点就是如何选两个点,由于n和m最大就是10,所以可以枚举每个点。这里我选择用vector存储每个草坪(自我感觉会快一点,不用遍历数组)。 还有一个难点是如何描述两个点同时开始烧的这个状态,或者说怎么确定最小值。看上去要两个点同时进行BFS,其实不用(同时BFS实现上也困难),我们只需要先将初始的两个点放进队列里,再一个一个进行BFS即可,这里我选择用一个tempvis数组表示每个点是否被烧过(烧过为1,没有烧过或者是空地就为0),这样就保证了不会重复走,也就相当于保证了走的顺序。用一个cnt记录草坪的总数量,tcnt记录走过的草坪的数量。当队列为空的时候我们并不知道是否还有剩余的草坪,所以只有当tcnt == cnt的时候才能说明所有的草坪都被烧光,此时记录一下时间。

坑点: x,y 与 行和列 容易搞反!






#include<iostream>#include<cstdio>#include<string.h>#include<math.h>#include<string>#include<map>#include<set>#include<vector>#include<algorithm>#include<queue>#include<iomanip>using namespace std;const int INF = 0x3f3f3f3f;const int NINF = 0xc0c0c0c0;typedef pair<int,int> P;struct Point {    int x,y;    int step;};int n,m;int tcnt;char maze[10][10];int dx[4] = {1,0,-1,0};int dy[4] = {0,1,0,-1};bool vis[10][10];queue<Point> q;bool tempvis[10][10];void bfs(Point p){    tempvis[p.y][p.x] = 1;        for(int i=0;i<4;i++){            Point dp = p;            dp.x += dx[i];            dp.y += dy[i];            if(dp.x >= 0 && dp.x < m && dp.y >= 0 && dp.y <n && tempvis[dp.y][dp.x] == 0){                dp.step++;                tcnt++;                q.push(dp);                tempvis[dp.y][dp.x] = 1;            }        }}void init(){    for(int i=0;i<n;i++){        for(int j=0;j<m;j++){            tempvis[i][j] = vis[i][j];        }    }}void print(){    for(int i=0;i<n;i++){        for(int j=0;j<m;j++){            cout << tempvis[i][j] <<' ';        }        cout << '\n';    }}int main(){    int T;    cin >> T;    int k=0;    while(T--){        vector<pair<int,int> > coor;        cin >> n >> m;        int cnt = 0;        for(int i=0;i<n;i++){            for(int j=0;j<m;j++){                cin >> maze[i][j];                if(maze[i][j] == '#'){                    coor.push_back(P(i,j));                    cnt++;                    vis[i][j] = 0;                }                else vis[i][j] = 1;            }        }        if(cnt == 1){            k++;            cout << "Case "<<k << ": ";            cout << 0 << endl;            continue;        }        int ans = INF;//初始化成无限大,若最后结果还是无限大则输出-1        int res = NINF;        for(int i=0;i<coor.size();i++){            for(int j=i+1;j<coor.size();j++){                init();     //每次更新tempvis                //print();                tcnt = 2;                Point p1,p2;                p1.y = coor[i].first;                p1.x = coor[i].second;                p2.y = coor[j].first;                p2.x = coor[j].second;                tempvis[p1.y][p1.x] = 1;                tempvis[p2.y][p2.x] = 1;                p1.step = 0;                p2.step = 0;                q.push(p1);                q.push(p2);                while(q.size()!=0){                    Point temp = q.front();                    q.pop();                    bfs(temp);                    if(q.size() == 0){    //队列为空时,最后一个元素的步数即为时间,但注意此时并不知道是否烧光了所有草坪。                        res = temp.step;                    }                }                //cout << "tcnt = " << tcnt << endl;                if(tcnt == cnt){    //判断是否烧光了所有草坪                     ans = min(ans,res);                }            }        }        k++;        cout << "Case " << k << ": ";        if(ans == INF) cout << -1 << endl;        else cout << ans << endl;    }}


0 0