01揹包問題的具體描述自行百度:
有N件物品和一個容量爲V的揹包。第i件物品的重量是c[i],價值是w[i]。
求解將哪些物品裝入揹包可使這些物品的重量總和不超過揹包容量,且價值總和最大。
(01揹包中這些物品每種都只有1個,每個物品只能裝一次)
基本問題
用子問題定義狀態:即f[i][v]表示前i件物品恰放入一個容量爲v的揹包可以獲得的最大價值。
則其狀態轉移方程便是:f[i][v]=max{ f[i-1][v], f[i-1][v-c[i]]+w[i] }。可以壓縮空間,f[v]=max{f[v],f[v-c[i]]+w[i]}
“將前i件物品放入容量爲v的揹包中”這個子問題,若只考慮第i件物品的策略(放或不放),那麼就可以轉化爲一個只牽扯前i-1件物品的問題。
如果不放第i件物品,那麼問題就轉化爲“前i-1件物品放入容量爲v的揹包中”,價值爲f[i-1][v];如果放第i件物品,
那麼問題就轉化爲“前i-1件物品放入剩下的容量爲v-c[i]的揹包中”,
此時能獲得的最大價值就是f [i-1][v-c[i]]再加上通過放入第i件物品獲得的價值w[i] 即f[i-1][v-c[i]]+w[i]。
爲什麼逆序
逆序的關鍵就在於這個狀態轉移方程
f[i][v]只與f[i-1][v]和f[i-1][v-C[i]]有關,即只和i-1時刻狀態有關,所以我們只需要用一維數組f[]來保存i-1時的狀態f[]。
假設i-1時刻的f[]爲{a0,a1,a2,…,av},那麼i時刻的f[]中第v個應該爲max(av,av-C[i]+W[i])即max(f[v],f[v-C[i]]+W[i]),
這就需要我們遍歷V時逆序遍歷,這樣才能保證求i時刻f[v]時f[v-C[i]]是i-1時刻的值。如果正序遍歷則當求f[v]時
其前面的f[0],f[1],…,f[v-1]都已經改變過,裏面存的都不是i-1時刻的值,這樣求f[v]時利用f[v-C[i]]必定是錯的值。最後f[V]即爲最大價值。
數組遍歷有時候必須逆序大多是這個原因。