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

 

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值