# 980. Unique Paths III

**<font color=red>难度: Hard</font>**

## 刷题内容

> 原题连接

* https://leetcode.com/problems/unique-paths-iii/

> 内容描述

```
On a 2-dimensional grid, there are 4 types of squares:

1 represents the starting square.  There is exactly one starting square.
2 represents the ending square.  There is exactly one ending square.
0 represents empty squares we can walk over.
-1 represents obstacles that we cannot walk over.
Return the number of 4-directional walks from the starting square to the ending square, that walk over every non-obstacle square exactly once.

 

Example 1:

Input: [[1,0,0,0],[0,0,0,0],[0,0,2,-1]]
Output: 2
Explanation: We have the following two paths: 
1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2)
2. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2)
Example 2:

Input: [[1,0,0,0],[0,0,0,0],[0,0,0,2]]
Output: 4
Explanation: We have the following four paths: 
1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2),(2,3)
2. (0,0),(0,1),(1,1),(1,0),(2,0),(2,1),(2,2),(1,2),(0,2),(0,3),(1,3),(2,3)
3. (0,0),(1,0),(2,0),(2,1),(2,2),(1,2),(1,1),(0,1),(0,2),(0,3),(1,3),(2,3)
4. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2),(2,3)
Example 3:

Input: [[0,1],[2,0]]
Output: 0
Explanation: 
There is no path that walks over every empty square exactly once.
Note that the starting and ending square can be anywhere in the grid.
 

Note:

1 <= grid.length * grid[0].length <= 20
```

## 解题方案

> 思路 1
******- 时间复杂度: O(4^(row * col))******- 空间复杂度: O(row * col)******


暴力dfs

```python
class Solution:
    def uniquePathsIII(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        row = len(grid)
        col = len(grid[0]) if row else 0
        start = []
        empty = set()
        for i in range(row):
            for j in range(col):
                if grid[i][j] == 1:
                    start = [i,j]
                elif grid[i][j] == 0:
                    empty.add((i,j))

        self.res = 0
        def helper(i, j, cnt, visited):
            if (i,j) in visited:
                return
            if not (0 <= i < row) or not (0 <= j < col) or grid[i][j] == -1:
                return

            if grid[i][j] == 2:
                if cnt == len(empty):
                    self.res += 1
                return

            if grid[i][j] == 0:
                cnt += 1

            visited.add((i,j))

            helper(i+1, j, cnt, set(k for k in visited)) # 这里注意一定要重新开一个set，不然会影响后面的visited
            helper(i, j+1, cnt, set(k for k in visited))
            helper(i, j-1, cnt, set(k for k in visited))
            helper(i-1, j, cnt, set(k for k in visited))

        helper(start[0], start[1], 0, set())
        return self.res
```





> 思路 2
******- 时间复杂度: O(4^(row * col))******- 空间复杂度: O(row * col)******



BackTracking DFS，同时用walked来存放我们已经走过多少步了，避免了思路一中visited可能带来的问题


```python
class Solution:
    def uniquePathsIII(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        row = len(grid)
        col = len(grid[0]) if row else 0
        start, walks = [], 0
        
        for i in range(row):
            for j in range(col):
                if grid[i][j] == 0:
                    walks += 1
                elif grid[i][j] == 1:
                    start = [i,j]
                    
        nexts = [[0,1], [0,-1], [1,0], [-1,0]]
        self.res = 0  
        
        def dfs(i, j, walked):
            if not (0 <= i < row) or not (0 <= j < col) or grid[i][j] < 0:
                return
            if grid[i][j] == 2 and walked == walks + 1:
                self.res += 1
                return
            val = grid[i][j]
            grid[i][j] = -2
            for nxt in nexts:
                dfs(i + nxt[0], j + nxt[1], walked + 1)
            grid[i][j] = val
            
        dfs(start[0], start[1], 0)
        return self.res
```




























































