FZU 2150 Fire Game

题目链接:FZU 2150 Fire Game

题目大意:
给出一个\(m\times 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;
}
posted @ 2020-10-04 20:47  ZZHHOOUU  阅读(207)  评论(0编辑  收藏  举报