Fire Game
题意:
给定一个数值 T ,表示测试案例数,每个测试案例给定一个 m * n 的网格板,’#’ 代表草地,’.’ 代表空地,任意选择两个(可以是同一个)草地放火,火可以往临近的四个网格中有草的地方蔓延,空地不会着火,假设每次蔓延需要1个单位时间,求要使得所有草地着火至少需要多少时间,若无法引燃所有草地,则输出 -1。(保证网格中至少有一个草地)
数据范围:
1 <= T <=100, 1 <= n <=10, 1 <= m <=10
解题思路:
宽度优先搜素
本题的特殊之处在于有两个起点
,因为本题数据不大,所以可以枚举
草地的两两不同组合作为起点入队,当然这两个起点可以相同,然后进行 bfs 的操作,再来判断是否已引燃所有草地,若是,则将这些符合要求的不同组合所花的时间互相比较,得到最短时间,若都不是,则输出 -1。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
using namespace std;
#define INF 0x3f3f3f
#define zero 1e-7
typedef long long ll;
const int N=15;
char mp[N][N];
bool vis[N][N];
int move[4][2]={{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int n, m;
struct node {
int x, y, dh;
};
vector<node> v;
queue<node> q;
void init() {
memset(vis, false, sizeof(vis));
while(!q.empty()) q.pop();
return ;
}
bool judge() {
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
if(mp[i][j]=='#' && !vis[i][j])
return false;
}
}
return true;
}
int bfs(node a, node b) {
init();
int deepest=0;
q.push(a);
q.push(b);
vis[a.x][a.y]=true;
vis[b.x][b.y]=true;
while(!q.empty()) {
node g=q.front();
q.pop();
deepest=g.dh;
for(int i=0; i<4; i++) {
int dx=g.x+move[i][0];
int dy=g.y+move[i][1];
if(dx>=0 && dx<n && dy>=0 && dy<m && mp[dx][dy]=='#' && !vis[dx][dy]) {
vis[dx][dy]=true;
node next={dx, dy, g.dh+1};
q.push(next);
}
}
}
return deepest;
}
int main() {
int T;
scanf("%d", &T);
for(int t=1; t<=T; t++) {
v.clear();
scanf("%d %d", &n, &m);
for(int i=0; i<n; i++)
scanf(" %s", mp[i]);
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
if(mp[i][j]=='#') {
node gress={i, j, 0};
v.push_back(gress);
}
}
}
int ans=INF;
for(int i=0; i<v.size(); i++) {
for(int j=i; j<v.size(); j++) {
int temp=bfs(v[i], v[j]);
if(judge())
ans=min(ans, temp);
}
}
if(ans==INF) ans=-1;
printf("Case %d: %d\n", t, ans);
}
return 0;
}