题目链接:FZU 2150 Fire Game
题目大意:
给出一个(m imes n)的图,‘#’表示草坪,‘.’表示空地,然后可以选择在任意的两个草坪格子点火,火每(1)s会向周围四个格子扩散,问选择那两个点使得燃烧所有的草坪花费时间最小?
题解:
双起点BFS,枚举两个起点同时压入队列中,注意‘#’个数(<=1)要特判。
题目要求走过所有‘#’,所以BFS的循环不需要手动退出。
#include <iostream>
#include <queue>
using namespace std;
#define pii pair<int, int>
#define INF 0x3f3f3f3f
int T, n, m, cnt, ans, step[12][12];
char mat[12][12];
pii node[110];
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};
int bfs(pii x, pii y) {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
step[i][j] = INF;
}
}
queue <pii> q;
step[x.first][x.second] = step[y.first][y.second] = 0;
q.push(x), q.push(y);
pii temp;
while (!q.empty()) {
temp = q.front();
q.pop();
for (int i = 0;i < 4; ++i) {
int nx = temp.first + dx[i], ny = temp.second + dy[i];
if (nx > 0 && nx <= n && ny > 0 && ny <= m && mat[nx][ny] == '#' && step[nx][ny] == INF) {
step[nx][ny] = step[temp.first][temp.second] + 1;
q.push(make_pair(nx, ny));
}
}
}
for (int i = 1; i <= cnt; ++i) {
if (step[node[i].first][node[i].second] == INF) {
return INF;
}
}
return step[temp.first][temp.second];
}
int main() {
cin >> T;
for (int t = 1; t <= T; ++t) {
cnt = 0;
ans = INF;
cin >> n >> m;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
cin >> mat[i][j];
if (mat[i][j] == '#') {
node[++cnt].first = i, node[cnt].second = j;
}
}
}
if (cnt <= 1) {
cout << "Case " << t << ": " << 0 << endl;
}
for (int i = 1; i <= cnt; ++i) {
for (int j = i + 1; j <= cnt; ++j) {
ans = min(ans, bfs(node[i], node[j]));
}
}
if (ans == INF) {
cout << "Case " << t << ": " << -1 << endl;
} else {
cout << "Case " << t << ": " << ans << endl;
}
}
return 0;
}