動態規劃-01揹包

題目描述

給定n個重量爲w1,w2,,wnw_1,w_2,\cdots,w_n,價值爲v1,v2,,vnv_1,v_2,\cdots,v_n的物品和容量爲C的揹包,求這個物品中一個最有價值的子集,使得在滿足揹包的容量的前提下,包內的總價值最大。

01揹包指的是物品裝或者不裝裝且只能裝一次

i 1 2 3 4
w(體積) 2 3 4 5
v(價值) 3 4 5 6

分析

  • 方法一:利用回溯法進行解題求滿足條件的所有子集中價值最大的即可,但是時間複雜度是O(2n)O(2^n)見此博客

  • 方法二:利用二維動態規劃進行求解。

    • 狀態表示:F(n,C)F(n,C),表示前n個物品,裝到容量c的袋子裏,得到的最大價值。
      • 不放第n個物品,此時總價值爲F(n1,C)F(n-1,C)
      • 放置第n個物品,此時總價值爲vn+F(n1,Cwn)v_n+F(n-1,C-w_n)
    • 狀態轉移公式:F(i,C)=max(F(i1,C),v(i)+F(i1,Cw(i)))F(i,C)=max(F(i−1,C),v(i)+F(i−1,C−w(i)))
    • 邊界:
      在這裏插入圖片描述

動態規劃自底向上二維表:
在這裏插入圖片描述

代碼

class Solution:
	def Solve01bag(self, n, C, w, v):
		# 行爲揹包容量
		# 列爲物品數
		dp = [[0 for _ in range(C+1)] for _ in range(n+1)]

		for i in range(1, n+1): #物品索引從零開始
			for j in range(1, C+1):
				dp[i][j] = dp[i-1][j]
				if j>=w[i-1]:
					dp[i][j]= max(dp[i][j], v[i-1]+dp[i-1][j-w[i-1]])


		return dp[n][C]


if __name__ == '__main__':

	test = Solution()

	res = test.Solve01bag(4, 8, [2,3,4,5], [3,4,5,6])

	print(res)
#[[0, 0, 0, 0, 0, 0, 0, 0, 0], 
# [0, 0, 3, 3, 3, 3, 3, 3, 3], 
# [0, 0, 3, 4, 4, 7, 7, 7, 7],
# [0, 0, 3, 4, 5, 7, 8, 9, 9],
# [0, 0, 3, 4, 5, 7, 8, 9, 10]]
#10
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章