题目地址:
https://leetcode.com/problems/minimum-moves-to-reach-target-with-rotations/description/
给定一个 n n n阶二维 01 01 01矩阵, 1 1 1代表障碍物, 0 0 0代表空地。有一条蛇,其占两个格子,其一开始在 ( 0 , 0 ) , ( 0 , 1 ) (0,0),(0,1) (0,0),(0,1)两个格子,它想去 ( n − 1 , n − 2 ) , ( n − 1 , n − 1 ) (n-1,n-2),(n-1,n-1) (n−1,n−2),(n−1,n−1)这个位置。其头部在 ( 0 , 1 ) (0,1) (0,1)这个位置,最后想去 ( n − 1 , n − 1 ) (n-1,n-1) (n−1,n−1)这个位置。它每一步可以向右移动一格(整个身子向右平移),也可以向下移动一格(也是整个身子平移),只要不碰到障碍物;如果其朝向右,其也可以绕着其尾巴顺时针旋转 90 ° 90\degree 90°,类似的,其朝向下的时候,也可以绕着尾巴逆时针旋转 90 ° 90\degree 90°,但旋转的必要条件不但是它的终止位置不能有障碍物,其扫过的格子也不能有障碍物(即尾巴右下一格的位置)。问最少多少步可以爬到终点。
可以将其尾巴位置和头的朝向做成一个三元组 ( x , y , d ) (x,y,d) (x,y,d),如果 d = 0 d=0 d=0代表朝右, d = 1 d=1 d=1是朝下。那么即问从 ( 0 , 0 , 0 ) (0,0,0) (0,0,0)到 ( n − 1 , n − 2 , 0 ) (n-1,n-2,0) (n−1,n−2,0)需要多少步。可以用BFS来做。代码如下:
class Solution {
public:
struct Node {
int x, y, d;
bool operator==(const Node& p) const {
return x == p.x && y == p.y && d == p.d;
}
};
int minimumMoves(vector<vector<int>>& g) {
int n = g.size();
if (g[n - 1][n - 1] == 1 || g[n - 1][n - 2] == 1) return -1;
auto nhash = [](const Node& p) {
return hash<int>()(p.x) ^ hash<int>()(p.y) ^ hash<int>()(p.d);
};
queue<Node> q;
q.push({0, 0, 0});
bool vis[n][n][2];
memset(vis, 0, sizeof vis);
vis[0][0][0] = true;
auto can_go = [&](int x, int y) {
return 0 <= x && x < g.size() && 0 <= y && y < g[0].size() && !g[x][y];
};
Node end{n - 1, n - 2, 0};
int res = 0;
while (q.size()) {
res++;
for (int _ = q.size(); _; _--) {
auto t = q.front();
q.pop();
int x = t.x, y = t.y, d = t.d;
int hx, hy;
if (!d) hx = x, hy = y + 1;
else hx = x + 1, hy = y;
// right
if (can_go(hx, hy + 1) && can_go(x, y + 1)) {
Node ne = {x, y + 1, d};
if (ne == end) return res;
if (!vis[x][y + 1][d]) {
vis[x][y + 1][d] = true;
q.push(ne);
}
}
// down
if (can_go(hx + 1, hy) && can_go(x + 1, y)) {
Node ne = {x + 1, y, d};
if (ne == end) return res;
if (!vis[x + 1][y][d]) {
vis[x + 1][y][d] = true;
q.push(ne);
}
}
if (can_go(x + 1, y + 1)) {
if (!d && can_go(x + 1, y)) {
Node ne = {x, y, 1};
if (!vis[x][y][1]) {
vis[x][y][1] = true;
q.push(ne);
}
}
if (d && can_go(x, y + 1)) {
Node ne = {x, y, 0};
if (!vis[x][y][0]) {
vis[x][y][0] = true;
q.push(ne);
}
}
}
}
}
return -1;
}
};
时空复杂度 O ( n 2 ) O(n^2) O(n2)。