LeetCode198 DP:打家劫舍

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

示例 1:
输入: [1,2,3,1]
输出: 4
解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。

示例 2:
输入: [2,7,9,3,1]
输出: 12
解释: 偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
偷窃到的最高金额 = 2 + 9 + 1 = 12 。

动态规划的解题条件

如果一个问题有三个性质,那么它大概率可以使用动态规划来解:

  • 无后向性
    • 本阶段决策无需考虑之后阶段的决策,其实大多数符合多阶段最优解模型的问题都具有这个性质。
  • 最优子结构
    • 一个问题的最优解,包含了其子问题的最优解。
  • 重复子问题
    • 在被分解的问题中,存在重复的子问题,使用剪枝减少计算。

动态规划

动态规划的的四个解题步骤是

  • 定义子问题
  • 写出子问题的递推关系
  • 确定 DP 数组的计算顺序
  • 空间优化(可选)

要点

  • 最优子结构:保证将要求解的大问题划分成小问题,通过小问题求解的正确性。
  • 状态表示:具体定义状态的含义。
  • 状态转移方程:找到状态之间的递推式。
  • 边界条件:用编程的思想将边界条件就是为了给递推式提供出口。

状态数组

  • 记录在当前子问题下的最优解

解题代码

import re

def func(nums):
	if not nums:
		return 0
	arr_len = len(nums)

	# sum_arr = [0] * arr_len
	first = nums[0]
	if arr_len <= 1:
		return first

	second = max(nums[0], nums[1])
	if arr_len > 2:
	    for n in range(2, arr_len):
	    	tmp = second
	        second = max(first+nums[n], second)
	        first = tmp
	return second

arr_list = re.split(r'[\[\],]', input())[1:-1]
for arr_index in range(len(arr_list)):
	arr_list[arr_index] = int(arr_list[arr_index])
# print(arr_list)
arr_len = len(arr_list)
print(func(arr_list))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章