P1126 机器人搬重物 题解
思路解析
这道题我们看到地图立马想到使用搜索,然而我们发现这里有 \(5\) 种操作,如果进行 DFS 的话状态数太多(也许可以优化?),所以我们采用 BFS。
其实这道题并不需要建图,但考虑到一种一直在原地空转的情况,所以在搜索过程中不能在一个位置停留,但是考虑到这里转向也需要花时间,那么也就是说我们不仅要记录此时的坐标,也要记录此时的朝向才能判断一个点是否重复经过。
我们都会写寻常的走路 BFS,这里走多步路怎么写?需要注意的是这里如果你走的小步的时候撞到了墙,那么你走大步路的时候一定也会撞到墙,也就是这里的走路并不是量子跃迁,而是真实的走路。
还有一个需要考虑的点是:题目中说机器人是一个以格点为圆心的 \(1.6 \text{m}\) 为半径的圆(扫地机器人?),也就是说这个机器人可以被一个 \(2 \times 2\) 的正方形完全包住。
也就是说这个扫地机器人不能在边界走,会撞墙,而且一定要在格点里走,但题目里给的障碍是一块一块的所以要把题目中给的地图转化为点图,把四个角设置为障碍即可。
这里的旋转如何维护?
我们想到,旋转是以 \(360 \degree\) 为周期的,向左转实际上可以转化为向右转,考虑到转 \(360 \degree\) 之后朝向是不变的,那么我们只要向右转 \(360 \degree - 90 \degree = 270 \degree\) 就是向左转 \(90 \degree\)。
这个东西很想数论里的模运算,设当前朝向为 \(t\),\(0\) 代表东,\(1\) 代表南,\(2\) 代表西,\(3\) 代表北,我们钦定向右转为 \(t' = (t + 1) \bmod 4\),那么向左转也就是 \(t' = (t + 4 - 1) \bmod 4 = (t + 3) \bmod 4\)。
代码实现
这里用了优先队列,但是实际上不用,因为晚入队的一定是时间晚的。所以实现的好的话可以去掉一个 \(\log\)。
#include <bits/stdc++.h>
using namespace std;
const int N = 65, Nto = 5, dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
struct node {
int x, y, st, to;
bool operator<(const node &rhs) const { return st > rhs.st; }
};
int n, m, sx, sy, ex, ey;
bool mp[N][N], tmp[N][N], vis[N][N][Nto];
char toword;
priority_queue<node> q;
map<char, int> towards;
inline void init() {
towards['E'] = 0, towards['S'] = 1, towards['W'] = 2, towards['N'] = 3;
return;
}
inline void bfs() {
q.push({sx, sy, 0, towards[toword]});
vis[sx][sy][towards[toword]] = true;
for (; !q.empty();) {
auto [x, y, st, to] = q.top();
q.pop();
if (x == ex && y == ey) {
cout << st;
return;
}
for (int i = 1, nx, ny; i <= 3; i++) {
nx = x + dx[to] * i, ny = y + dy[to] * i;
if (mp[nx][ny]) {
break;
}
if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && !vis[nx][ny][to]) {
vis[nx][ny][to] = true;
q.push({nx, ny, st + 1, to});
}
}
int turn_left = (to + 1) % 4, turn_right = (to + 3) % 4;
if (!vis[x][y][turn_left]) {
vis[x][y][turn_left] = true;
q.push({x, y, st + 1, turn_left});
}
if (!vis[x][y][turn_right]) {
vis[x][y][turn_right] = true;
q.push({x, y, st + 1, turn_right});
}
}
cout << "-1";
return;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
init();
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> tmp[i][j];
if (tmp[i][j]) {
mp[i][j] = mp[i + 1][j] = mp[i][j + 1] = mp[i + 1][j + 1] = true;
}
}
}
cin >> sx >> sy >> ex >> ey >> toword;
n++, m++, sx++, sy++, ex++, ey++;
for (int i = 1; i <= n; i++) {
mp[i][1] = mp[i][m] = mp[i][0] = mp[i][m + 1] = true;
}
for (int i = 1; i <= m; i++) {
mp[1][i] = mp[n][i] = mp[0][i] = mp[n + 1][i] = true;
}
bfs();
return 0;
}

浙公网安备 33010602011771号