打家劫舍(動態規劃)

2021-10-06 10:40:44 字數 1623 閱讀 8248

打家劫舍(ⅰ)

你是乙個專業的小偷,計畫偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。

給定乙個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。

考慮所有可能的搶劫方案過於困難。乙個自然而然的想法是首先從最簡單的情況開始。記:

f(k) = 從前 k 個房屋中能搶劫到的最大數額,a_ia i = 第 i 個房屋的錢數。

首先看 n = 1 的情況,顯然 f(1) = a_1a 1 。

再看 n = 2,f(2) = max(a_1a 1 , a_2a 2 )。

對於 n = 3,有兩個選項:

搶第三個房子,將數額與第乙個房子相加。

不搶第三個房子,保持現有最大數額。

顯然,你想選擇數額更大的選項。於是,可以總結出公式:

f(k) = max(f(k – 2) + a_ka k , f(k – 1))

我們選擇 f(–1) = f(0) = 0 為初始情況,這將極大地簡化**。

答案為 f(n)。可以用乙個陣列來儲存並計算結果。不過由於每一步你只需要前兩個最大值,兩個變數就足夠用了。

class solution:

def rob(self, nums: list[int]) -> int:

n = len(nums)

if n == 0:

return 0

pre = cur = 0

for c in nums:

pre, cur = cur, max(pre + c, cur)

return cur

打家劫舍(ⅱ)

你是乙個專業的小偷,計畫偷竊沿街的房屋,每間房內都藏有一定的現金。這個地方所有的房屋都圍成一圈,這意味著第乙個房屋和最後乙個房屋是緊挨著的。同時,相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。

給定乙個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。

環狀排列意味著第乙個房子和最後乙個房子中只能選擇乙個偷竊,因此可以把此環狀排列房間問題約化為兩個單排排列房間子問題:

在不偷竊第乙個房子的情況下(即 nums[1:]nums[1:]),最大金額是 p_1p1;在不偷竊最後乙個房子的情況下(即 nums[:n-1]nums[:n−1]),最大金額是 p_2p 2 。綜合偷竊最大金額: 為以上兩種情況的較大值,即 max(p1,p2)max(p1,p2) 。

class solution:

def rob(self, nums: [int]) -> int:

def my_rob(nums):

cur, pre = 0, 0

for num in nums:

cur, pre = max(pre + num, cur), cur

return cur

return max(my_rob(nums[:-1]),my_rob(nums[1:])) if len(nums) != 1 else nums[0]

動態規劃 打家劫舍

你是乙個專業的小偷,計畫偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。給定乙個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。示例 1 輸入 1...

打家劫舍 動態規劃

你是乙個專業的小偷,計畫偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。給定乙個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。示例 1 輸入 1...

動態規劃 打家劫舍

遵紀守法,人人有責!動態規劃 dynamic programming,dp 是運籌學的乙個分支,是求解決策過程最優化的過程。通俗點 對於某類問題,可以拆分成若干個子問題,按照順序求解子問題的解,前乙個子問題的解,為後乙個問題提供相關資訊,每個子問題的解不能隨意確定。依次下去,就能形成一條解決問題的子...