Skip to content

Latest commit

 

History

History
268 lines (229 loc) · 8.52 KB

File metadata and controls

268 lines (229 loc) · 8.52 KB

English Version

题目描述

你还记得那条风靡全球的贪吃蛇吗?

我们在一个 n*n 的网格上构建了新的迷宫地图,蛇的长度为 2,也就是说它会占去两个单元格。蛇会从左上角((0, 0) 和 (0, 1))开始移动。我们用 0 表示空单元格,用 1 表示障碍物。蛇需要移动到迷宫的右下角((n-1, n-2) 和 (n-1, n-1))。

每次移动,蛇可以这样走:

  • 如果没有障碍,则向右移动一个单元格。并仍然保持身体的水平/竖直状态。
  • 如果没有障碍,则向下移动一个单元格。并仍然保持身体的水平/竖直状态。
  • 如果它处于水平状态并且其下面的两个单元都是空的,就顺时针旋转 90 度。蛇从((r, c)(r, c+1))移动到 ((r, c)(r+1, c))。
  • 如果它处于竖直状态并且其右面的两个单元都是空的,就逆时针旋转 90 度。蛇从((r, c)(r+1, c))移动到((r, c)(r, c+1))。

返回蛇抵达目的地所需的最少移动次数。

如果无法到达目的地,请返回 -1

 

示例 1:

输入:grid = [[0,0,0,0,0,1],
               [1,1,0,0,1,0],
               [0,0,0,0,1,1],
               [0,0,1,0,1,0],
               [0,1,1,0,0,0],
               [0,1,1,0,0,0]]
输出:11
解释:
一种可能的解决方案是 [右, 右, 顺时针旋转, 右, 下, 下, 下, 下, 逆时针旋转, 右, 下]。

示例 2:

输入:grid = [[0,0,1,1,1,1],
               [0,0,0,0,1,1],
               [1,1,0,0,0,1],
               [1,1,1,0,0,1],
               [1,1,1,0,0,1],
               [1,1,1,0,0,0]]
输出:9

 

提示:

  • 2 <= n <= 100
  • 0 <= grid[i][j] <= 1
  • 蛇保证从空单元格开始出发。

解法

方法一:BFS

Python3

class Solution:
    def minimumMoves(self, grid: List[List[int]]) -> int:
        def check(a, b):
            if (a, b) not in vis:
                vis.add((a, b))
                q.append((a, b))

        n = len(grid)
        target = (n * n - 2, n * n - 1)
        q = deque([(0, 1)])
        vis = {(0, 1)}
        ans = 0
        while q:
            for _ in range(len(q)):
                a, b = q.popleft()
                if (a, b) == target:
                    return ans
                i1, j1 = a // n, a % n
                i2, j2 = b // n, b % n
                if (
                    j1 + 1 < n
                    and j2 + 1 < n
                    and grid[i1][j1 + 1] == 0
                    and grid[i2][j2 + 1] == 0
                ):
                    check(i1 * n + j1 + 1, i2 * n + j2 + 1)
                    if j1 == j2:
                        check(a, i1 * n + j2 + 1)
                if (
                    i1 + 1 < n
                    and i2 + 1 < n
                    and grid[i1 + 1][j1] == 0
                    and grid[i2 + 1][j2] == 0
                ):
                    check((i1 + 1) * n + j1, (i2 + 1) * n + j2)
                    if i1 == i2:
                        check(a, (i2 + 1) * n + j1)
            ans += 1
        return -1

Java

class Solution {
    public int minimumMoves(int[][] grid) {
        int n = grid.length;
        int[] target = new int[] {n * n - 2, n * n - 1};
        Deque<int[]> q = new ArrayDeque<>();
        q.offer(new int[] {0, 1});
        boolean[][] vis = new boolean[n * n][n * n];
        int ans = 0;
        vis[0][1] = true;
        while (!q.isEmpty()) {
            for (int k = q.size(); k > 0; --k) {
                int[] p = q.poll();
                if (p[0] == target[0] && p[1] == target[1]) {
                    return ans;
                }
                int a = p[0], b = p[1];
                int i1 = a / n, j1 = a % n;
                int i2 = b / n, j2 = b % n;
                if (j1 + 1 < n && j2 + 1 < n && grid[i1][j1 + 1] == 0 && grid[i2][j2 + 1] == 0) {
                    check(i1 * n + j1 + 1, i2 * n + j2 + 1, q, vis);
                    if (j1 == j2) {
                        check(a, i1 * n + j2 + 1, q, vis);
                    }
                }
                if (i1 + 1 < n && i2 + 1 < n && grid[i1 + 1][j1] == 0 && grid[i2 + 1][j2] == 0) {
                    check((i1 + 1) * n + j1, (i2 + 1) * n + j2, q, vis);
                    if (i1 == i2) {
                        check(a, (i2 + 1) * n + j1, q, vis);
                    }
                }
            }
            ++ans;
        }
        return -1;
    }

    private void check(int a, int b, Deque<int[]> q, boolean[][] vis) {
        if (!vis[a][b]) {
            vis[a][b] = true;
            q.offer(new int[] {a, b});
        }
    }
}

C++

class Solution {
public:
    int minimumMoves(vector<vector<int>>& grid) {
        int n = grid.size();
        vector<int> target = {n * n - 2, n * n - 1};
        queue<vector<int>> q;
        q.push({0, 1});
        vector<vector<bool>> vis(n * n, vector<bool>(n * n));
        int ans = 0;
        vis[0][1] = true;
        while (!q.empty()) {
            for (int k = q.size(); k; --k) {
                auto p = q.front();
                if (p == target) return ans;
                q.pop();
                int a = p[0], b = p[1];
                int i1 = a / n, j1 = a % n;
                int i2 = b / n, j2 = b % n;
                if (j1 + 1 < n && j2 + 1 < n && grid[i1][j1 + 1] == 0 && grid[i2][j2 + 1] == 0) {
                    check(i1 * n + j1 + 1, i2 * n + j2 + 1, q, vis);
                    if (j1 == j2) check(a, i1 * n + j2 + 1, q, vis);
                }
                if (i1 + 1 < n && i2 + 1 < n && grid[i1 + 1][j1] == 0 && grid[i2 + 1][j2] == 0) {
                    check((i1 + 1) * n + j1, (i2 + 1) * n + j2, q, vis);
                    if (i1 == i2) check(a, (i2 + 1) * n + j1, q, vis);
                }
            }
            ++ans;
        }
        return -1;
    }

    void check(int a, int b, queue<vector<int>>& q, vector<vector<bool>>& vis) {
        if (!vis[a][b]) {
            vis[a][b] = true;
            q.push({a, b});
        }
    }
};

Go

func minimumMoves(grid [][]int) int {
	n := len(grid)
	target := []int{n*n - 2, n*n - 1}
	q := [][]int{{0, 1}}
	vis := make([][]bool, n*n)
	for i := range vis {
		vis[i] = make([]bool, n*n)
	}
	vis[0][1] = true
	ans := 0
	check := func(a, b int) {
		if !vis[a][b] {
			vis[a][b] = true
			q = append(q, []int{a, b})
		}
	}
	for len(q) > 0 {
		for k := len(q); k > 0; k-- {
			p := q[0]
			q = q[1:]
			if p[0] == target[0] && p[1] == target[1] {
				return ans
			}
			a, b := p[0], p[1]
			i1, j1 := a/n, a%n
			i2, j2 := b/n, b%n
			if j1+1 < n && j2+1 < n && grid[i1][j1+1] == 0 && grid[i2][j2+1] == 0 {
				check(i1*n+j1+1, i2*n+j2+1)
				if j1 == j2 {
					check(a, i1*n+j2+1)
				}
			}
			if i1+1 < n && i2+1 < n && grid[i1+1][j1] == 0 && grid[i2+1][j2] == 0 {
				check((i1+1)*n+j1, (i2+1)*n+j2)
				if i1 == i2 {
					check(a, (i2+1)*n+j1)
				}
			}
		}
		ans++
	}
	return -1
}

...