leetcode的揹包問題

2021-10-04 09:41:53 字數 3648 閱讀 1757

n件物品和乙個容量為v的揹包。第i件物品的費用是w[i],價值是v[i],求將哪些物品裝入揹包可使價值總和最大。

定義陣列

dp[i]

[j] # 代表前i個商品,放入乙個容量為j的揹包,所獲得的最大價值

初始化

# 如果要求恰好放滿揹包,則陣列初始化為 -inf

dp =[[

-inf]

*(amount +1)

for _ in range

(n)]

# 如果要求恰好放滿揹包,則陣列初始化為 0

dp =[[

0]*(amount +1)

for _ in range

(n)]

需要格外強調的是:第

一、無論初始化是如何進行的,但是我們每次迭代商品的時候:dp[i][0]一定要等於0,因為放滿容量為0的揹包,價值肯定是0。第

二、動態陣列的長度是(容量+1)(要考慮容量為0的情形)。

轉移方程

for i in range

(n+1

): # 初始化工作對i==

0的時候已經做了處理,所以這裡可以不用再考慮。

for j in range

(w[i]

,v+1

): # 正序

f[i]

[j]=

max(f[i−1

][j]

,f[i−1

][j−w[i]

]+v[i]

)

我們觀察轉移方程:

f[i]

[j]=

max(f[i−1

][j]

,f[i−1

][j−w[i]

]+v[i]

)

發現f[i][j]只和上一行正上方上一行的左上方有關。如果我們只用一行資料正序遍歷的話,我們會將上一行左上方的資料先覆蓋掉。所以我們採用逆序遍歷。

def package_01

(size, values, weights)

:# dp[j]代表裝滿容量為j的揹包能產生的最大價值

import numpy

# 如果不要求完全裝滿

dp = numpy.

array([

0]*(size +1)

) # 如果要求完全裝滿

# dp = [-float("inf")] * (size + 1)

# 初始化,無論是要求裝滿還是不裝滿,初始化規則一樣,只是如果要求不裝滿,已經是0,可以省略初始化條件

dp[0]

=0for i in range

(len

(values)):

for j in range

(size, weights[i]-1

,-1)

: # 逆序

dp[j]

=max

(dp[j]

, dp[j - weights[i]

]+ values[i]

)return dp[size]

n種商品和乙個容量為v的揹包。第i件物品有無數件,且費用是w[i],價值是v[i],求將哪些物品裝入揹包可使價值總和最大。

完全揹包和01揹包的邏輯基本類似,但是由於物品可以任意次取,所以我們每個物品取用多少次 取決於當0<=k*w[i]<=j時,f[i−1][j−k*w[i]]+k*v[i]最大。

f[i]

[j]=

max(f[i−1

][j−k*w[i]

]+k*v[i])0

<=k*w[i]

<=j

將上面的邏輯轉為程式語言

k =

1while k * weights[i]

<= j:

dp[i]

[j]=

max(dp[i]

[j], dp[i -1]

[j - k * weights[i]

]+ k * weights[i]

) k +

=1

最終解法:

def package_total

(size, values, weights)

: import numpy

# 如果不要求完全裝滿

dp = numpy.

array([

[0]*

(size +1)

for _ in range

(len

(values))]

) # 初始化,無論是要求裝滿還是不裝滿,初始化規則一樣,只是如果要求不裝滿,已經是0,可以省略初始化條件

dp[0]

[0]=

0for i in range

(len

(values)):

for j in range

(weights[i]

, size +1)

: k =

1while k * weights[i]

<= j:

dp[i]

[j]=

max(dp[i]

[j], dp[i -1]

[j - k * weights[i]

]+ k * weights[i]

) k +=1

return dp[-1

][-1

]

def package_total

(size, values, weights)

:# dp[j]代表裝滿容量為j的揹包能產生的最大價值

import numpy

# 如果不要求完全裝滿

dp = numpy.

array([

0]*(size +1)

) # 如果要求完全裝滿

# dp = [-float("inf")] * (size + 1)

# 初始化,無論是要求裝滿還是不裝滿,初始化規則一樣,只是如果要求不裝滿,已經是0,可以省略初始化條件

dp[0]

=0for i in range

(len

(values)):

for j in range

(weights[i]

, size +1)

: # 正序

dp[j]

=max

(dp[j]

, dp[j - weights[i]

]+ values[i]

)return dp[size]

Leetcode揹包問題

題意 幾種無限數量的硬幣,湊成amount的方案數,方案是無序的,即1 2 和 2 1算同一種 題解 方法一 經典揹包解法 dp i j 表示前i個物品湊出j的方案數,考慮第i個選與不選兩種情況,其中選的時候,再考慮選擇第i個物品的次數。class solution return dp n amou...

Leetcode 0 1揹包問題

什麼是揹包問題?比如有n個物品,它們有各自的體積和價值,現有給定容量的揹包,如何讓揹包裡裝入的物品具有最大的價值總和?0 1揹包問題就是這n個物品中某乙個物品選還是不選,分別表示1和0 題目描述 比如有n個物品,它們有各自的體積w和價值v,現有給定容量的揹包ba 如何讓揹包裡裝入的物品具有最大的價值...

揹包問題 01揹包問題

n個物品,總體積是v,每個物品的體積的vi,每個物品的最大價值是wi,在不超過v的體積下求最大價值 eg揹包容積為 5 物品數量為 4 物品的體積分別為 物品的價值分別為 思路定義乙個二位陣列int f new int n 1 v 1 f i j 就表示在1 i個物品中選取體積小於v的情況的最大價值...