# 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. `1 <= grid.length * grid[0].length <= 20`

```java
class Solution {
    int[][] directions = { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } };

    public boolean isPossible(int grid[][], boolean[][] visited, int x, int y) {
        if (x >= 0 && x < grid.length && y >= 0 && y < grid[x].length && !visited[x][y] && grid[x][y] != -1)
            return true;
        return false;
    }

    int ans = 0;

    public int uniquePathsIII(int[][] grid) {
        int rowStart = 0, colStart = 0, rowEnd = 0, colEnd = 0, count = 0;
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if (grid[i][j] == 1) {
                    rowStart = i;
                    colStart = j;
                } else if (grid[i][j] == 2) {
                    rowEnd = i;
                    colEnd = j;
                } else if (grid[i][j] == 0)
                    count++;
            }
        }
        boolean[][] visited = new boolean[grid.length][grid[0].length];
        backtrack(grid, visited, rowStart, colStart, rowEnd, colEnd, 0, count);
        return ans;
    }

    public void backtrack(int[][] grid, boolean[][] visited, int x, int y, int xEnd, int yEnd, int currentCount,
            int totalCount) {
        if (isPossible(grid, visited, x, y)) {
            if (x == xEnd && y == yEnd) {
                if (currentCount == totalCount)
                    ans++;
            } else {
                visited[x][y] = true;
                for (int i = 0; i < 4; i++) {
                    backtrack(grid, visited, x + directions[i][0], y + directions[i][1], xEnd, yEnd,
                            currentCount + (grid[x][y] == 0 ? 1 : 0), totalCount);
                }
                visited[x][y] = false;
            }
        }
    }
}
```
