對使用倒序的一維陣列解決0/1揹包問題的理解
大略的題目:
n個物品的價值,從這些物品中選出一些(可能全選)並裝入容積為v的揹包,求揹包中的物品的最大價值。
輸入: v,n, 接下來第一行是各個物品的體積v,第二行是各個物品的價值w。
輸出: 揹包能裝入的物品的最大價值。
要想理解這個問題,可以使用**來說明、使用二維陣列的解法來做對比。
測試資料:
9 3
5 3 4
3 5 4
首先看二維陣列**(已經明白了就跳過):
view code
1 # include 2 # include接著看這種解法的dp表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 }
再看一維陣列寫法:
(為了和二維陣列的**比較,我做了盡量少的改變)
view code
1 # include 2 # include接著看這種解法的dp表: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[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 請問在她臨走之前...