题目描述
本题要求模拟一个矩形池塘中多只乌龟的移动行为。池塘被建模为一个 N×MN \times MN×M 的网格,乌龟位于网格的整数坐标位置上。每只乌龟可以接受八个方向的移动指令:N、S、E、W、NE、NW、SE、SW。移动规则如下:
- 如果目标位置超出网格边界,移动被忽略;
- 如果目标位置已被其他乌龟占据,移动被忽略;
- 否则,乌龟移动到目标位置。
输入包含多个数据集,每个数据集给出池塘尺寸、乌龟初始位置和一系列移动指令。要求输出所有指令执行后的池塘状态图。
输入格式
- 第一行四个整数:NNN MMM TTT KKK
- NNN:南北方向网格数
- MMM:东西方向网格数
- TTT:乌龟数量
- KKK:移动指令数
- 接下来 TTT 行,每行三个整数:乌龟 ID\texttt{ID}ID 初始行坐标 初始列坐标
- 接下来 KKK 行,每行一个乌龟 ID\texttt{ID}ID 和一个方向字符串
输出格式
- 用 ASCII 字符绘制 NNN 行网格图
- 有乌龟的位置输出
*,空位置输出空格 - 每行末尾不能有空格
- 每个数据集后输出一个空行
解题思路
问题分析
本题属于网格模拟类问题,需要处理多个对象在有限空间中的移动,并检测位置冲突。关键在于高效地跟踪每个乌龟的位置,并在移动时快速判断目标位置的合法性。
数据结构设计
-
乌龟位置存储:使用
std::map<int, std::pair<int, int>>将乌龟 ID\text{ID}ID 映射到坐标位置,便于通过 ID\texttt{ID}ID 快速查找。 -
位置占用标记:使用二维数组
vector<vector<bool>> occupied记录每个网格位置是否被占用,实现 O(1)O(1)O(1) 时间的冲突检测。 -
方向映射:使用
std::map<std::string, std::pair<int, int>>将方向字符串映射为坐标偏移量。
算法流程
-
初始化阶段:
- 读取池塘尺寸和乌龟数量
- 记录每只乌龟的初始位置
- 初始化位置占用标记数组
-
指令处理阶段:
- 对于每个移动指令:
- 检查乌龟 ID\texttt{ID}ID 是否存在
- 计算目标坐标
- 检查边界和位置冲突
- 如果移动合法,更新乌龟位置和占用标记
- 对于每个移动指令:
-
输出阶段:
- 根据最终位置填充字符网格
- 逐行输出,去除行尾空格
- 输出数据集间的空行
复杂度分析
- 时间复杂度:O(K+N×M)O(K + N \times M)O(K+N×M),其中 KKK 是指令数,N×MN \times MN×M 是输出网格大小
- 空间复杂度:O(N×M+T)O(N \times M + T)O(N×M+T),用于存储网格和乌龟位置
代码实现
// Sala-ma-Sond A Nice Little Pond
// UVa ID: 10156
// Verdict: Accepted
// Submission Date: 2025-11-23
// UVa Run Time: 0.110s
//
// 版权所有(C)2025,邱秋。metaphysis # yeah dot net
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m, t, k;
// 处理多个数据集
while (cin >> n >> m >> t >> k) {
// 存储乌龟ID到坐标的映射
map<int, pair<int, int>> turtles;
// 标记网格位置是否被占用
vector<vector<bool>> occupied(n, vector<bool>(m, false));
// 读取乌龟初始位置
for (int i = 0; i < t; i++) {
int id, x, y;
cin >> id >> x >> y;
turtles[id] = {x, y};
occupied[x][y] = true;
}
// 定义八个方向的坐标偏移量
map<string, pair<int, int>> dirs = {
{"N", {-1, 0}}, {"S", {1, 0}}, {"E", {0, 1}}, {"W", {0, -1}},
{"NE", {-1, 1}}, {"NW", {-1, -1}}, {"SE", {1, 1}}, {"SW", {1, -1}}
};
// 处理移动指令
for (int i = 0; i < k; i++) {
int id;
string dir;
cin >> id >> dir;
// 检查乌龟ID是否存在
if (turtles.find(id) == turtles.end()) continue;
// 获取当前位置
int x = turtles[id].first, y = turtles[id].second;
// 计算目标位置
int dx = dirs[dir].first, dy = dirs[dir].second;
int nx = x + dx, ny = y + dy;
// 检查边界
if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
// 检查位置冲突
if (occupied[nx][ny]) continue;
// 更新位置:先释放原位置,再占用新位置
occupied[x][y] = false;
occupied[nx][ny] = true;
turtles[id] = {nx, ny};
}
// 输出最终状态
for (int i = 0; i < n; i++) {
string line = "";
for (int j = 0; j < m; j++) {
if (occupied[i][j]) line += '*';
else line += ' ';
}
// 去除行尾空格
while (!line.empty() && line.back() == ' ') line.pop_back();
cout << line << endl;
}
cout << endl;
}
return 0;
}
关键要点
- 高效冲突检测:使用二维数组记录位置占用状态,避免每次遍历所有乌龟
- 原子性更新:移动时同时更新原位置和新位置的占用状态,保持数据一致性
- 输出格式控制:严格按要求去除行尾空格,确保格式正确
- 边界处理:仔细检查网格边界和乌龟 ID\texttt{ID}ID 的有效性
该解法通过合理的数据结构设计和细致的边界处理,能够高效正确地模拟乌龟在池塘中的移动行为。
6万+

被折叠的 条评论
为什么被折叠?



