这里要求通过所有的格点,所以最直接的方法是记录下所有格点数,然后暴力搜索,这里可以直接使用gird数组帮助来判断是否访问过。
全局变量搜索版本:
const int dx[] = {0, 1, -1, 0};
const int dy[] = {1, 0, 0, -1};
class Solution {
public:
int uniquePathsIII(vector<vector<int>>& grid) {
int startX = 0, startY = 0, endX = 0, endY = 0, num = 0;
for (int i = 0; i < grid.size(); i++) {
for (int j = 0; j < grid[0].size(); j++) {
if (grid[i][j] != -1) {
num++;
}
if (grid[i][j] == 1) {
startX = i;
startY = j;
}
if (grid[i][j] == 2) {
endX = i;
endY = j;
}
}
}
dfs(grid, startX, startY, endX, endY, num);
return res;
}
int res = 0;
void dfs(vector<vector<int>>& grid, int x, int y, int endX, int endY, int num) {
num--;
if (num < 0) {
return;
}
if (x == endX && y == endY) {
if (num == 0) {
res++;
}
return;
}
grid[x][y] = -1;
for (int i = 0; i < 4; i++) {
int a = x + dx[i];
int b = y + dy[i];
if (a >= 0 && a < grid.size() && b >=0 && b < grid[0].size() && grid[a][b] != -1) {
dfs(grid, a, b, endX, endY, num);
}
}
grid[x][y] = 0;
num++;
}
};
状态函数版本:
const int dx[] = {0, 1, -1, 0};
const int dy[] = {1, 0, 0, -1};
class Solution {
public:
int uniquePathsIII(vector<vector<int>>& grid) {
int startX = 0, startY = 0, endX = 0, endY = 0, num = 0;
for (int i = 0; i < grid.size(); i++) {
for (int j = 0; j < grid[0].size(); j++) {
if (grid[i][j] != -1) {
num++;
}
if (grid[i][j] == 1) {
startX = i;
startY = j;
}
if (grid[i][j] == 2) {
endX = i;
endY = j;
}
}
}
return dfs(grid, startX, startY, endX, endY, num);
}
int dfs(vector<vector<int>>& grid, int x, int y, int endX, int endY, int num) {
num--;
if (num < 0) {
return 0;
}
if (x == endX && y == endY) {
return (num == 0 ? 1 : 0);
}
int res = 0;
grid[x][y] = -1;
for (int i = 0; i < 4; i++) {
int a = x + dx[i];
int b = y + dy[i];
if (a >= 0 && a < grid.size() && b >=0 && b < grid[0].size() && grid[a][b] != -1) {
res += dfs(grid, a, b, endX, endY, num);
}
}
grid[x][y] = 0;
num++;
return res;
}
};
方法二:用状态压缩进行记忆话搜索
class Solution:
def uniquePathsIII(self, grid: List[List[int]]) -> int:
R, C = len(grid), len(grid[0])
def code(r, c):
return 1 << (r * C + c)
def neighbors(r, c):
for nr, nc in ((r-1, c), (r, c-1), (r+1, c), (r, c+1)):
if 0 <= nr < R and 0 <= nc < C and grid[nr][nc] % 2 == 0:
yield nr, nc
target = 0
for r, row in enumerate(grid):
for c, val in enumerate(row):
if val % 2 == 0:
target |= code(r, c)
if val == 1:
sr, sc = r, c
if val == 2:
tr, tc = r, c
@lru_cache(None)
def dp(r, c, todo):
if r == tr and c == tc:
return (todo == 0)
ans = 0
for nr, nc in neighbors(r, c):
if todo & code(nr, nc):
ans += dp(nr, nc, todo ^ code(nr, nc))
return ans
return dp(sr, sc, target)