980. 不同路径 III
在二维网格 grid 上,有 4 种类型的方格:
1 表示起始方格。且只有一个起始方格。
2 表示结束方格,且只有一个结束方格。
0 表示我们可以走过的空方格。
-1 表示我们无法跨越的障碍。
返回在四个方向(上、下、左、右)上行走时,从起始方格到结束方格的不同路径的数目。
每一个无障碍方格都要通过一次,但是一条路径中不能重复通过同一个方格。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/unique-paths-iii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
深度优先搜索
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
class Solution {
private int ans = 0;
private int[][] directions = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
private void solve(int[][] grid, Pair from, Pair end, int total) {
if (total < 0) {
return;
}
if (total == 0 || from.equals(end)) {
if (total == 0 && from.equals(end)) {
ans++;
}
return;
}
for (int i = 0; i < directions.length; ++i) {
int x = from.x + directions[i][0];
int y = from.y + directions[i][1];
Pair to = new Pair(x, y);
if (x >= 0 && x < grid.length && y >= 0 && y < grid[0].length && grid[x][y] != -1) {
int t = grid[x][y];
grid[x][y] = -1;
solve(grid, to, end, total - 1);
grid[x][y] = t;
}
}
}
public int uniquePathsIII(int[][] grid) {
Pair start = null, end = null;
int total = grid.length * grid[0].length;
for (int i = 0; i < grid.length; ++i) {
for (int j = 0; j < grid[0].length; ++j) {
if (grid[i][j] == 1) {
start = new Pair(i, j);
} else if (grid[i][j] == 2) {
end = new Pair(i, j);
} else if (grid[i][j] == -1) {
total--;
}
}
}
grid[start.x][start.y] = -1;
solve(grid, start, end, total - 1);
return ans;
}
public static void main(String[] args) {
int[][] grid = {
{1, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 2, -1}};
System.out.println(new Solution().uniquePathsIII(grid));
}
}
class Pair {
int x;
int y;
public Pair(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair pair = (Pair) o;
return x == pair.x && y == pair.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
动态规划
class Solution {
private int[][] grid;
private int tr, tc;
private int[][] directions = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
private Integer[][][] memo;
public int uniquePathsIII(int[][] grid) {
this.grid = grid;
int target = 0;
int sr = 0, sc = 0;
for (int r = 0; r < grid.length; ++r)
for (int c = 0; c < grid[0].length; ++c) {
if (grid[r][c] % 2 == 0) {
target |= code(r, c);
}
if (grid[r][c] == 1) {
sr = r;
sc = c;
} else if (grid[r][c] == 2) {
tr = r;
tc = c;
}
}
memo = new Integer[grid.length][grid[0].length][1 << (grid.length * grid[0].length)];
return dp(sr, sc, target);
}
public int code(int r, int c) {
return 1 << (r * grid[0].length + c);
}
public Integer dp(int r, int c, int todo) {
if (memo[r][c][todo] == null) {
if (r == tr && c == tc) {
memo[r][c][todo] = todo == 0 ? 1 : 0;
} else {
int ans = 0;
for (int k = 0; k < 4; ++k) {
int nr = r + directions[k][0];
int nc = c + directions[k][1];
if (0 <= nr && nr < grid.length && 0 <= nc && nc < grid[0].length) {
if ((todo & code(nr, nc)) != 0) {
ans += dp(nr, nc, todo ^ code(nr, nc));
}
}
}
memo[r][c][todo] = ans;
}
}
return memo[r][c][todo];
}
}
心之所向,素履以往 生如逆旅,一苇以航