返回
打家劫舍 2:环形房屋的巧妙盗窃
后端
2024-01-10 06:20:21
打家劫舍 2——巧妙避开联动警报
引言
想象一下你是一个身经百战的窃贼,准备在环形街道上大显身手。每座房子都存放着不同金额的现金,但这些房子都连接着精密的防盗系统。一旦你触发了其中一间房子的警报,整条街的警报都会响起,你的盗窃计划将功亏一篑。现在,你的目标是找到一种方法,最大化你的战利品,同时避免触发任何警报。
环形劫掠的数学奥秘
打家劫舍 2 的本质是一个动态规划问题。假设你有 n 座房子,你需要确定一种方法来掠夺最多现金,同时避免触发任何警报。要做到这一点,你需要根据前面的决策来做出当前决策。
让我们考虑两种情况:
- 选择抢劫第一间房子: 如果你抢劫第一间房子,你不能抢劫相邻的第二间房子,因为它们连接着警报系统。因此,你将从第 3 间房子继续抢劫,并获得前 n-1 间房子的最大现金。
- 选择不抢劫第一间房子: 如果你不抢劫第一间房子,你可以抢劫第二间房子,并从第 3 间房子继续抢劫。在这种情况下,你将获得前 n-2 间房子的最大现金,加上第二间房子的现金。
通过比较这两种情况,你可以决定哪种方法能让你获得更多现金。
算法设计
基于上述观察,我们可以设计一个动态规划算法,计算从每座房子开始时能获得的最大现金:
- 初始化: 设置 dp[n+2] 数组,其中 dp[i] 表示从第 i 间房子开始时能获得的最大现金。
- 循环: 对于 i 从 2 循环到 n+1,执行以下步骤:
- 抢劫当前房子: dp[i] = nums[i] + dp[i+2],这表示抢劫当前房子并跳过相邻房子。
- 不抢劫当前房子: dp[i] = dp[i+1],这表示不抢劫当前房子,而从下一间房子继续抢劫。
- 结果: 返回 dp[2] 或 dp[3],具体取决于是抢劫还是不抢劫第一间房子。
代码实现
使用 Python 的代码实现如下:
def rob(nums):
n = len(nums)
if n == 0:
return 0
dp = [0] * (n + 2)
# 循环从第 2 间房子开始,因为第 1 间房子与最后 1 间房子相连
for i in range(2, n + 1):
dp[i] = max(nums[i - 1] + dp[i + 1], dp[i + 1])
# 返回从第 2 间或第 3 间房子开始时能获得的最大现金
return max(dp[2], dp[3])
结论
通过巧妙地利用动态规划,我们可以确定如何最大化打家劫舍 2 中的战利品,同时避免触发任何警报。这个策略确保我们在做出当前决策时考虑了所有可能的未来决策,从而引导我们走向最优解。无论你是想在游戏中大显身手,还是想解决现实世界中的复杂问题,打家劫舍 2 的教训都是宝贵的:通过明智的决策和对动态规划的理解,我们可以实现看似不可能的目标。