Skip to content

Latest commit

 

History

History
258 lines (226 loc) · 8.46 KB

File metadata and controls

258 lines (226 loc) · 8.46 KB

中文文档

Description

In an n*n grid, there is a snake that spans 2 cells and starts moving from the top left corner at (0, 0) and (0, 1). The grid has empty cells represented by zeros and blocked cells represented by ones. The snake wants to reach the lower right corner at (n-1, n-2) and (n-1, n-1).

In one move the snake can:

  • Move one cell to the right if there are no blocked cells there. This move keeps the horizontal/vertical position of the snake as it is.
  • Move down one cell if there are no blocked cells there. This move keeps the horizontal/vertical position of the snake as it is.
  • Rotate clockwise if it's in a horizontal position and the two cells under it are both empty. In that case the snake moves from (r, c) and (r, c+1) to (r, c) and (r+1, c).
  • Rotate counterclockwise if it's in a vertical position and the two cells to its right are both empty. In that case the snake moves from (r, c) and (r+1, c) to (r, c) and (r, c+1).

Return the minimum number of moves to reach the target.

If there is no way to reach the target, return -1.

 

Example 1:

Input: 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]]
Output: 11
Explanation:
One possible solution is [right, right, rotate clockwise, right, down, down, down, down, rotate counterclockwise, right, down].

Example 2:

Input: 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]]
Output: 9

 

Constraints:

  • 2 <= n <= 100
  • 0 <= grid[i][j] <= 1
  • It is guaranteed that the snake starts at empty cells.

Solutions

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
}

...