1210. Minimum Moves to Reach Target with Rotations

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.

思路:DP不太好弄,直接BFS
 

class Solution(object):
    def minimumMoves(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        n=len(grid)
        q,qq=[(0,0,0)],[]
        vis=set([(0,0,0)])
        step=0
        while q:
            while q:
                i,j,s=q.pop()
                if i==n-1 and j==n-2 and s==0: return step
                if s==0:
                    if i+1<n and grid[i+1][j]==0 and grid[i+1][j+1]==0 and (i,j,1) not in vis:
                        qq.append((i,j,1))
                        vis.add((i,j,1))
                    if j+2<n and grid[i][j+2]==0 and (i,j+1,s) not in vis:
                        qq.append((i,j+1,s))
                        vis.add((i,j+1,s))
                    if i+1<n and grid[i+1][j]==0 and grid[i+1][j+1]==0 and (i+1,j,s) not in vis:
                        qq.append((i+1,j,s))
                        vis.add((i+1,j,s))
                else:
                    if j+1<n and grid[i][j+1]==0 and grid[i+1][j+1]==0 and (i,j,0) not in vis:
                        qq.append((i,j,0))
                        vis.add((i,j,0))
                    if j+1<n and grid[i][j+1]==0 and grid[i+1][j+1]==0 and (i,j+1,s) not in vis:
                        qq.append((i,j+1,s))
                        vis.add((i,j+1,s))
                    if i+2<n and grid[i+2][j]==0 and (i+1,j,s) not in vis:
                        qq.append((i+1,j,s))
                        vis.add((i+1,j,s))
            
            q,qq=qq,q
            step+=1
        return -1
    
s=Solution()
print(s.minimumMoves([[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]]))

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值