ZCS的随机游走的题解
题目链接
我们看到这道题,一下子就可以想到用模拟来做,但是!地图存不下去,这是一个严重的问题。
怎么办呢?
方法一:
我们可以用不同的数字来代替字符,再用short存。
CODE:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
// 读取输入
int n, m, x;
cin >> n >> m >> x;
// 读取网格
vector<vector<short>> grid(n, vector<short>(m));
int start_i = 0, start_j = 0; // 初始位置
for (int i = 0; i < n; ++i) {
string row;
cin >> row;
for (int j = 0; j < m; ++j) {
if (row[j] == '#') {
start_i = i;
start_j = j;
grid[i][j] = 0; // 起点视为空地
} else if (row[j] == 'X') {
grid[i][j] = 1; // 1 表示障碍物
} else {
grid[i][j] = 0; // 0 表示空地
}
}
}
// 读取移动方向
vector<short> opts(x);
for (int i = 0; i < x; ++i) {
cin >> opts[i];
}
// 模拟游走
int current_i = start_i, current_j = start_j; // 当前位置
for (int i = 0; i < x; ++i) {
int opt = opts[i];
int next_i = current_i, next_j = current_j;
// 计算下一步的坐标
if (opt == 1) {
next_i--; // 上
} else if (opt == 2) {
next_i++; // 下
} else if (opt == 3) {
next_j--; // 左
} else if (opt == 4) {
next_j++; // 右
}
// 检查是否越界或撞到障碍物
if (next_i < 0 || next_i >= n || next_j < 0 || next_j >= m || grid[next_i][next_j] == 1) {
cout << "ZCS is die!" << endl;
return 0;
}
// 更新当前位置
current_i = next_i;
current_j = next_j;
}
// 输出最终坐标
cout << current_i - start_i << " " << current_j - start_j << endl;
return 0;
}
方法二:
我们把障碍用vector存下来。
CODE:
#include <iostream>
using namespace std;
// 定义方向偏移量,分别对应上、下、左、右
const int dx[] = {-1, 1, 0, 0};
const int dy[] = {0, 0, -1, 1};
int main() {
short n, m, x;
// 读取教室的长、宽和步数
cin >> n >> m >> x;
short startX, startY;
char cell;
// 读取地图并确定起点坐标
for (short i = 0; i < n; ++i) {
for (short j = 0; j < m; ++j) {
cin >> cell;
if (cell == '#') {
startX = j;
startY = i;
}
}
}
short currentX = startX;
short currentY = startY;
for (short i = 0; i < x; ++i) {
short opt;
cin >> opt;
// 方向选项减 1 以匹配偏移量数组的索引
opt--;
short newX = currentX + dx[opt];
short newY = currentY + dy[opt];
// 动态检查新位置是否越界或者遇到障碍
bool isInvalid = false;
if (newX < 0 || newX >= m || newY < 0 || newY >= n) {
isInvalid = true;
} else {
// 重新读取地图中对应位置的信息
short pos = newY * m + newX;
short currentRow = 0;
cin.clear();
cin.seekg(0, ios::beg);
for (short k = 0; k < n; ++k) {
for (short l = 0; l < m; ++l) {
cin >> cell;
if (k * m + l == pos) {
if (cell == 'X') {
isInvalid = true;
}
break;
}
}
if (isInvalid) {
break;
}
}
}
if (isInvalid) {
cout << "ZCS is die!" << endl;
return 0;
}
currentX = newX;
currentY = newY;
}
// 如果没有撞到障碍,输出最终坐标
cout << "(" << currentX - startX << ", " << currentY - startY << ")" << endl;
return 0;
}
注:有可能过不了。
方法三:
我们可以把经历过的坐标记录下来,用hash去重,并且看是否与某个障碍物的坐标重合了。
CODE:
#include <iostream>
#include <vector>
#include <string>
#include <unordered_set>
using namespace std;
// 定义一个哈希函数用于存储坐标
struct CoordinateHash {
size_t operator()(const pair<int, int>& p) const {
return static_cast<size_t>(p.first) * 100000 + p.second;
}
};
int main() {
// 读取输入
int n, m, x;
cin >> n >> m >> x;
// 读取网格
vector<string> grid(n);
int start_i = 0, start_j = 0; // 初始位置
for (int i = 0; i < n; ++i) {
cin >> grid[i];
for (int j = 0; j < m; ++j) {
if (grid[i][j] == '#') {
start_i = i;
start_j = j;
}
}
}
// 读取移动方向
vector<int> opts(x);
for (int i = 0; i < x; ++i) {
cin >> opts[i];
}
// 记录障碍物的坐标
unordered_set<pair<int, int>, CoordinateHash> obstacles;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (grid[i][j] == 'X') {
obstacles.insert({i - start_i, j - start_j});
}
}
}
// 模拟游走
int current_i = 0, current_j = 0; // 当前位置(相对于起点)
unordered_set<pair<int, int>, CoordinateHash> visited; // 记录走过的坐标
visited.insert({current_i, current_j});
for (int i = 0; i < x; ++i) {
int opt = opts[i];
int next_i = current_i, next_j = current_j;
// 计算下一步的坐标
if (opt == 1) {
next_i--; // 上
} else if (opt == 2) {
next_i++; // 下
} else if (opt == 3) {
next_j--; // 左
} else if (opt == 4) {
next_j++; // 右
}
// 检查是否撞到障碍物
if (obstacles.find({next_i, next_j}) != obstacles.end()) {
cout << "ZCS is die!" << endl;
return 0;
}
// 检查是否越界
if (next_i < -start_i || next_i >= n - start_i || next_j < -start_j || next_j >= m - start_j) {
cout << "ZCS is die!" << endl;
return 0;
}
// 更新当前位置
current_i = next_i;
current_j = next_j;
visited.insert({current_i, current_j});
}
// 输出最终坐标
cout << current_i << " " << current_j << endl;
return 0;
}
多么简单的一道题。