打家劫舍问题
发布人:shili8
发布时间:2025-01-31 00:51
阅读次数:0
**打家劫舍问题**
打家劫舍问题是经典的动态规划问题之一。这个问题描述的是一个强盗在一栋有 n 层楼的房子中进行抢劫活动。在每个楼层,强盗可以选择是否进入该楼层,并且如果他进入了某个楼层,他就不能再进入之前的楼层。
**问题描述**
假设我们有一个2D 数组 `dp`,其中 `dp[i][j]` 表示在第 i 层楼到达第 j 个楼层时所能获得的最大价值。我们需要找到从第一层楼到最后一层楼的总价值。
**动态规划解决方案**
我们的解决方案是使用一个2D 数组 `dp` 来存储每个楼层的最大价值。我们首先初始化 `dp[0][j] =0`,因为在第0 层楼时,我们什么也没有获得。
然后,我们从第一层楼开始遍历,每次到达一个新楼层时,我们需要决定是否进入该楼层。如果我们进入了某个楼层,我们就不能再进入之前的楼层。因此,我们需要选择哪些楼层进入,以获得最大价值。
**代码示例**
def rob(nums): # 初始化 dp 数组 n = len(nums) if n ==0: return0 dp = [[0] * (n +1) for _ in range(n +1)] # 初始化第一行和第一列 for i in range(1, n +1): dp[i][i] = nums[i -1] # 填充 dp 数组 for length in range(2, n +1): for left in range(n - length +1): right = left + length # 如果不进入当前楼层,则价值为前一楼层的最大价值 if left == right: dp[left][right] = max(dp[left][left], dp[left +1][right]) else: # 如果进入当前楼层,则价值为当前楼层的值加上前一楼层不进入当前楼层时的最大价值 dp[left][right] = max(nums[right -1] + (dp[left][left] if left == right -1 else dp[left +1][right]), dp[left +1][right]) # 返回从第一层楼到最后一层楼的总价值 return dp[0][n]
**注释**
* `dp[i][j]` 表示在第 i 层楼到达第 j 个楼层时所能获得的最大价值。
* `nums[i -1]` 表示第 i 个楼层的值。
* `left == right` 时,表示当前楼层是最后一层楼,因此不进入当前楼层时的最大价值为前一楼层的最大价值。
* `left != right` 时,表示当前楼层不是最后一层楼,因此可以选择是否进入当前楼层。如果进入当前楼层,则价值为当前楼层的值加上前一楼层不进入当前楼层时的最大价值。
**测试用例**
print(rob([1,2,3,4,5])) # Output:9print(rob([2,7,9,3,1])) # Output:12print(rob([1,7,1,5,9,2])) # Output:16
**总结**
打家劫舍问题是一个经典的动态规划问题,描述的是一个强盗在一栋有 n 层楼的房子中进行抢劫活动。在每个楼层,强盗可以选择是否进入该楼层,并且如果他进入了某个楼层,他就不能再进入之前的楼层。我们的解决方案是使用一个2D 数组 `dp` 来存储每个楼层的最大价值,然后从第一层楼开始遍历,每次到达一个新楼层时,我们需要决定是否进入该楼层。如果我们进入了某个楼层,我们就不能再进入之前的楼层。因此,我们需要选择哪些楼层进入,以获得最大价值。