《P2960 [USACO09OCT] Invasion of the Milkweed G》
题目描述
农夫约翰一直尽力保持牧场里长满丰盛、美味且健康的草供奶牛食用。然而,他输掉了这场战斗,因为邪恶的乳草在他的农场西北部站稳了脚跟。
牧场通常被划分为一个直角网格,高度为 Y(1≤Y≤100),宽度为 X(1≤X≤100),其中 (1,1) 位于左下角(即,排列为正常的 X,Y 坐标网格)。乳草最初开始在方格 (Mx,My) 生长。每周,乳草会传播到它已经占据的任何方格周围的所有非岩石方格,最多可以传播到八个方格(包括直角方格和对角线方格)。在这些方格中仅仅一周后,它就准备好继续传播到更多方格。
贝茜想在牧场被乳草占领之前尽可能多地享受青草。她想知道牧场能持续多久。如果乳草在时间零时位于方格 (Mx,My),那么它在何时完成对牧场的入侵(对于给定的输入数据,这种情况总会发生)?
牧场由一个图示描述,'.' 代表草,'*' 代表巨石,如下例所示,X=4,Y=3:
....
..*.
.**.
如果乳草从左下角开始(行=1,列=1),那么地图将按如下方式演变:
.... .... MMM. MMMM MMMM..*. MM*. MM*. MM*M MM*MM**. M**. M**. M**. M**M
week 0 1 2 3 4
乳草在 4 周后占领了整个牧场。
输入格式
* 第 1 行:四个以空格分隔的整数:X,Y,Mx 和 My
* 第 2 行到第 Y+1 行:第 y+1 行描述了牧场的第 (Y+2−y) 行,其中包含 X 个字符('.' 代表草,'*' 代表巨石)
输出格式
* 第 1 行:一个整数,表示乳草占领牧场最后一个非巨石方格的周数。
显示翻译
题意翻译
输入输出样例
输入 #1复制
4 3 1 1 .... ..*. .**.
输出 #1复制
4
说明/提示
(由 ChatGPT 4o 翻译)
代码实现:
#include <iostream>
#include <vector>
#include <queue>
#include <string>
using namespace std;
// 定义8个方向的偏移量(上、下、左、右及四个对角线方向)
const int dx[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
const int dy[8] = {-1, 0, 1, -1, 1, -1, 0, 1};
int main() {
int X, Y, Mx, My;
cin >> X >> Y >> Mx >> My;
// 调整坐标,使其从0开始索引(更符合编程习惯)
Mx--;
My = Y - My; // 因为题目中(1,1)在左下角,转换为从0开始的索引时需要调整
// 读取牧场地图
vector<string> pasture(Y);
for (int i = 0; i < Y; i++) {
cin >> pasture[i];
}
// 记录每个位置被占领的时间,-1表示未被占领或为巨石
vector<vector<int> > time(Y, vector<int>(X, -1));
queue<pair<int, int> > q;
// 检查起始位置是否为草
if (pasture[My][Mx] == '.') {
time[My][Mx] = 0; // 时间从0开始
q.push(make_pair(My, Mx));
}
int result = 0;
// BFS过程
while (!q.empty()) {
pair<int, int> current = q.front();
q.pop();
int y = current.first;
int x = current.second;
// 尝试向8个方向扩散
for (int i = 0; i < 8; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
// 检查新位置是否在边界内,是否为草,是否未被占领
if (nx >= 0 && nx < X && ny >= 0 && ny < Y &&
pasture[ny][nx] == '.' && time[ny][nx] == -1) {
time[ny][nx] = time[y][x] + 1; // 时间+1
q.push(make_pair(ny, nx));
result = max(result, time[ny][nx]); // 更新最大时间
}
}
}
cout << result << endl;
return 0;
}