對使用倒序的一維陣列解決0 1揹包問題的理解

2022-03-20 20:12:39 字數 2553 閱讀 2616

對使用倒序的一維陣列解決0/1揹包問題的理解

大略的題目:

n個物品的價值,從這些物品中選出一些(可能全選)並裝入容積為v的揹包,求揹包中的物品的最大價值。

輸入: v,n, 接下來第一行是各個物品的體積v,第二行是各個物品的價值w。

輸出: 揹包能裝入的物品的最大價值。

要想理解這個問題,可以使用**來說明、使用二維陣列的解法來做對比。

測試資料:

9  3

5  3  4

3  5  4

首先看二維陣列**(已經明白了就跳過):

view code

1 # include 2 # include 

3 # define max(a, b) a>b ? a : b //

巨集替換4

5int dp[1010][1010], w[1010], v[1010]; //

dp是動態規劃的簡寫,dp[i][j]代表前i個元素裝進容量為j的揹包的最優解67

intmain () else

27if (j == 0) continue;//

列印dp**

28 printf("

%5d", dp[i][j]);//

列印dp**29}

30 putchar(10);//

列印dp**31}

32 printf("

%d\n

", dp[n][v]);//

輸出前n個物品裝入容積為v的揹包的最優解33}

3435

return0;

36 }

接著看這種解法的dp表

再看一維陣列寫法:

(為了和二維陣列的**比較,我做了盡量少的改變)

view code

1 # include 2 # include 

3 # define max(a, b) a>b ? a : b //

巨集替換4

5int dp[1010], w[1010], v[1010]; //

dp是動態規劃的簡寫,當迴圈到第i次時,dp[j]代表前i個元素裝進容量為j的揹包的最優解67

intmain () else

28if (j == 0) continue;//

列印dp**

29 printf("

%5d", dp[j]);//

列印dp**30}

31 putchar(10);//

列印dp**32}

33 printf("

%d\n

", dp[v]);//

輸出前n個物品裝入容積為v的揹包的最優解34}

3536

return0;

37 }

接著看這種解法的dp表:

可以發現,這兩種寫法導致了dp表左右相反。

二維dp寫法的狀態轉移公式表明當前的dp值需要用dp表上面乙個數值和左上的數值來確定。

那麼一維dp寫法是怎麼實現狀態的轉換的呢?根據狀態轉換公式dp[j]可能等於dp[j](迴圈到i時的dp[j]和迴圈到i-1時的dp[j]是不同的! )即上面乙個數值,

也可能等於dp[j-v[i]],即右上的數值。(這點比較難想到,原先我以為和二維的一樣是由左上和上面的值推出來的)

為什麼一維陣列寫法不能用順序呢?我們看一下順序dp表:

比較一下二維寫法的dp表可以發現第2行、第三行的第6列之後的數值不對了,為什麼呢?

以第二行第六列為例,此時i = 2, j = 6。dp[6] = max(dp[6], dp[6-v[2]]+w[2])    --①

也即dp[6] = max(3, dp[6-3]+5)  --②

也即dp[6] = max(3, 5+5)

所以dp[6] = 10。

①式中的max中的dp[6]是指i=1時的dp[6],而max外的dp[6]是指i=2時的dp[6]。

②式中的dp[6-3],即dp[3],是指i=2時的dp[3],而不是i=1時的dp[3],原因是遍歷到i=2,j=6時dp[3]已經被更新為i=2層的dp[3],

但是狀態轉移方程要求max中的dp是上一層的,而不是當前層的,所以從此開始dp表的值開始出錯。

再返回來看一維dp的倒序寫法,由於先更新下標比較大的dp陣列元素,此時通過狀態轉移方程求最大值的時候還未更新下標較小的dp陣列元素,

即下標較小的dp陣列元素還是上一層的值,因此倒序的方法可以使用!

至此,我們就能夠全部理解為什麼能用一維陣列來解決0/1揹包問題了。

本文結束。

0 1揹包使用一維陣列

使用滾動陣列將空間優化到了2 v,在揹包九講中提到了使用一維陣列也可以達到同樣的效果,個人認為這也是滾動思想的一種,由於使用一維陣列解01揹包會被多次用到,完全揹包的一種優化實現方式也是使用一維陣列,所以我們有必要理解這種方法。如果只使用一維陣列f 0 v 我們要達到的效果是 第i次迴圈結束後f v...

一維dp陣列01揹包

有n件物品和乙個最多能被重量為w 的揹包。第i件物品的重量是weight i 得到的價值是value i 每件物品只能用一次,求解將哪些物品裝入揹包裡物品價值總和最大。這是標準的揹包問題,以至於很多同學看了這個自然就會想到揹包,甚至都不知道暴力的解法應該怎麼解了。這樣其實是沒有從底向上去思考,而是習...

小梁的揹包(01揹包 一維陣列)

時間限制 c c 2秒,其他語言4秒 空間限制 c c 262144k,其他語言524288k 64bit io format lld 題目描述 小梁來到了伽勒爾地區並參加了聯盟賽熱身賽,比賽小島上有n個精靈散落在島上各處,她有乙個大小為s的揹包,每個精靈的戰鬥值為vi 體積為wi 請問在她臨走之前...