174. Leetcode 980. 不同路径 III (图算法-哈密尔顿路径)

174. Leetcode 980. 不同路径 III (图算法-哈密尔顿路径)_第1张图片

 174. Leetcode 980. 不同路径 III (图算法-哈密尔顿路径)_第2张图片

class Solution:
    DIRECTIONS = [(0,1),(1,0),(0,-1),(-1,0)]
    def uniquePathsIII(self, grid: List[List[int]]) -> int:
        self._grid = grid
        self._R = len(grid)
        self._C = len(grid[0])
        self._visited = [[False] * self._C for _ in range(self._R)]
        self._left = self._R * self._C

        for i in range(self._R):
            for j in range(self._C):
                if self._grid[i][j] == 1:
                    self._start = i * self._C + j
                    self._grid[i][j] = 0
                elif self._grid[i][j] == 2:
                    self._end = i * self._C + j
                    self._grid[i][j] = 0
                elif self._grid[i][j] == -1:
                    self._left -= 1

        return self._dfs(self._start, self._left)

    def _dfs(self, v, left):
        x = v // self._C
        y = v % self._C
        self._visited[x][y] = True
        left -= 1

        if left == 0 and v == self._end:
            self._visited[x][y] = False
            return 1
        
        res = 0
        for dx,dy in self.DIRECTIONS:
            nextx = x + dx
            nexty = y + dy
            if self._in_area(nextx, nexty) and self._grid[nextx][nexty] == 0 and not self._visited[nextx][nexty]:
                res += self._dfs(nextx * self._C + nexty, left)
        self._visited[x][y] = False
        return res

    def _in_area(self,x,y):
        return x >= 0 and x < self._R and y >= 0 and y < self._C




# 优化-状态压缩

class Solution:
    DIRECTIONS = [(0,1),(1,0),(0,-1),(-1,0)]
    def uniquePathsIII(self, grid: List[List[int]]) -> int:
        self._grid = grid
        self._R = len(grid)
        self._C = len(grid[0])
        self._visited = 0
        self._left = self._R * self._C

        for i in range(self._R):
            for j in range(self._C):
                if self._grid[i][j] == 1:
                    self._start = i * self._C + j
                    self._grid[i][j] = 0
                elif self._grid[i][j] == 2:
                    self._end = i * self._C + j
                    self._grid[i][j] = 0
                elif self._grid[i][j] == -1:
                    self._left -= 1

        return self._dfs(self._visited, self._start, self._left)

    def _dfs(self, visited, v, left):
        self._visited += (1 << v)
        left -= 1
        if left == 0 and v == self._end:
            self._visited -= (1 << v)
            return 1

        x = v // self._C
        y = v % self._C        
        res = 0
        for dx,dy in self.DIRECTIONS:
            nextx = x + dx
            nexty = y + dy
            next_ = nextx * self._C + nexty
            if self._in_area(nextx, nexty) and self._grid[nextx][nexty] == 0 and (self._visited & (1 << next_)) == 0:
                res += self._dfs(self._visited, next_, left)
        
        self._visited -= (1 << v)

        return res

    def _in_area(self,x,y):
        return x >= 0 and x < self._R and y >= 0 and y < self._C


# 记忆化搜索

class Solution:
    DIRECTIONS = [(0,1),(1,0),(0,-1),(-1,0)]
    def uniquePathsIII(self, grid: List[List[int]]) -> int:
        self._grid = grid
        self._R = len(grid)
        self._C = len(grid[0])
        self._left = self._R * self._C
        self._memo = [
            [-1] * (self._R * self._C)
            for _ in range(1 << self._R * self._C)
        ]

        for i in range(self._R):
            for j in range(self._C):
                if self._grid[i][j] == 1:
                    self._start = i * self._C + j
                    self._grid[i][j] = 0
                elif self._grid[i][j] == 2:
                    self._end = i * self._C + j
                    self._grid[i][j] = 0
                elif self._grid[i][j] == -1:
                    self._left -= 1

        visited = 0
        return self._dfs(visited, self._start, self._left)

    def _dfs(self, visited, v, left):
        if self._memo[visited][v] != -1:
            return self._memo[visited][v]

        visited += (1 << v)
        left -= 1
        if left == 0 and v == self._end:
            self._memo[visited][v] = 1
            return 1

        x = v // self._C
        y = v % self._C        
        res = 0
        for dx,dy in self.DIRECTIONS:
            nextx = x + dx
            nexty = y + dy
            next_ = nextx * self._C + nexty
            if self._in_area(nextx, nexty) and self._grid[nextx][nexty] == 0 and (visited & (1 << next_)) == 0:
                res += self._dfs(visited, next_, left)
        
        self._memo[visited][v] = res

        return res

    def _in_area(self,x,y):
        return x >= 0 and x < self._R and y >= 0 and y < self._C

174. Leetcode 980. 不同路径 III (图算法-哈密尔顿路径)_第3张图片

 记忆化搜索针对数据中重复边比较少的情况会出现大量的存储记忆比较耗时,记忆化搜索不一定比较好。

你可能感兴趣的:(2022刷题-目标400+,图论)