動態規劃 01揹包問題

2022-08-16 08:54:12 字數 2252 閱讀 4598

01揹包問題是動態規劃中最基礎的問題之一,它的解法完美地體現了動態規劃的思想和性質。

01揹包問題最常見的問題形式是:給定n件物品的體積和價值,將他們盡可能地放入乙個體積固定的揹包,最大的價值可以是多少。我們可以用費用c和價值v來描述一件物品,再設允許的最大花費為w。只要n稍大,我們就不可能通過搜尋來遍查所有組合的可能。運用動態規劃的思想,我們把原來的問題拆分為子問題,子問題再進一步拆分直至不可再分(初始值),隨後從初始值開始,盡可能地求取每乙個子問題的最優解,最終就能求得原問題的解。由於不同的問題可能有相同的子問題,子問題存在大量重疊,我們需要額外的空間來儲存已經求得的子問題的最優解。這樣,可以大幅度地降低時間複雜度。

有了這樣的思想,我們來看01揹包問題可以怎樣拆分成子問題:

要求解的問題是:在n件物品中最大花費為w能得到的最大價值。顯然,對於0 <= i <= n,0 <= j <= w,在前i件物品中最大花費為j能得到的最大價值。

可以使用陣列dp[n + 1][w + 1]來儲存所有的子問題,dp[i][j]就代表從前i件物品中選出總花費不超過j時的最大價值

可知dp[0][j]值一定為零。那麼,該怎麼遞推求取所有子問題的解呢。顯而易見,要考慮在前i件物品中拿取,首先要考慮前i - 1件物品中拿取的最優情況。

當我們從第i - 1件物品遞推到第i件時,我們就要考慮這件物品是拿,還是不拿,怎樣收益最大。

①:首先,如果j < c[i],那第i件物品是無論如何拿不了的,dp[i][j] = dp[i - 1][j];

②:如果可以拿,那就要考慮拿了之後收益是否更大。拿這件物品需要花費c[i],除去這c[i]的子問題應該是dp[i - 1][j - c[i]],這時,就要比較dp[i - 1][j]和dp[i - 1][j - c[i]] + v[i],得出最優方案。

細節和**如下:

int

n, w;

int c[maxn], v[maxn];//

c為費用,v為價值

intdp[maxn][maxw];

intmain()

memset(dp,

0, sizeof(dp));//

若不涉及多組輸入,這一步其實可以省略

//如果下標從0開始,下面也需要稍作修改

for(int i = 1;i <= n;i++)

}printf(

"%d\n

", dp[n][w]);

}

這樣做,時間複雜度和空間複雜度都是o(nw)

在上面的解法中,我們把所有子問題的最優解都用陣列儲存了下來,實際上,這些最優解並不是一直都有用的。從狀態轉移方程可以看出,對當前的i,只有i - 1時的最優解才是有用的,再之前的已經不會再被使用了。如果能把已經無用的空間節省出來,空間複雜度能夠得到非常大的優化,這在有些問題中是非常必要的。

實際上,只需要乙個一維的陣列dp[m + 1](省去n那一維)就可以完成任務。外層的迴圈每一輪開始時,這個陣列裡存的要麼是初始值(i = 0的情況),要麼是上一輪遞推得到的值(i - 1時的情況),符合原本狀態轉移方程的要求。

不過,這樣做就需要更加的注意遞推的方向,更新的順序。在更新前,陣列裡儲存的是上一輪的值(或初始值),更新後,更新了的位置儲存的就是這一輪的值了。在01揹包的問題裡,我們要從i - 1的情況遞推上來,所以要倒著更新。這一點需要著重理解(反了的話就變成完全揹包了)。

**如下:

int c[maxn], v[maxn];//

c為費用,v為價值

intdp[maxw];

//其餘部分略

for(int i = 1;i <= n;i++)

}

實踐中很難遇到如此標準的01揹包模型,大多數情況下,我們都需要根據具體問題對上面的演算法做出一定的修改。

這些問題都是揹包問題常見的,解決方法也都相同或者相似:

1.求取的不是價值的最大值而是最小值:把max換成min即可,原理相同。

4.要求恰好裝滿,即選取的物品的費用之和恰等於最大花費:

相比基礎的01揹包,這裡我們需要乙個正常情況不可能出現的值來表示狀態非法、不可能實現,這個值可以是-1、-inf之類的,視具體情況而定。

在初始化時,除dp[i][0]的值應為0之外,其他所有值都應為非法值。在狀態轉移時,首先要判斷子問題是否非法。

for(int i = 1;i <= w;i++)//

初始化dp[

0] = 0

;for(int i = 1;i <= n;i++)

}}

動態規劃揹包問題 01揹包

問題描述 n種物品,每種乙個。第i種物品的體積為vi,重量為wi。選一些物品裝到容量為c的揹包,使得揹包內物品不超過c的前提下,重量最大。問題分析 宣告乙個f n c 的陣列。f i j 表示把前i件物品都裝到容量為j的揹包所獲得的最大重量。當 j v i 時,揹包容量不足以放下第 i 件物品,f ...

動態規劃 揹包問題 01揹包

有n種物品和乙個容量為v的揹包,每種物品僅用一次。第i件物品的費用是w i 價值是v i 求解將哪些物品裝入揹包可使價值總和最大。例如 n 5,v 10 重量 價值 第乙個物品 10 5 第二個物品 1 4 第三個物品 2 3 第四個物品 3 2 第五個物品 4 1 首先我們考慮貪心策略,選取最大價...

0 1揹包問題(動態規劃)

一 問題描述 有n件物品和乙個容量為v的揹包。第i件物品的費用是c i 價值是w i 求解將哪些物品裝入揹包可使價值總和最大。所謂01揹包,表示每乙個物品只有乙個,要麼裝入,要麼不裝入。二 解決方案 考慮使用動態規劃求解,定義乙個遞迴式 opt i v 表示前i個物品,在揹包容量大小為v的情況下,最...