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))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章