完全揹包 動態規劃

2022-09-18 06:21:47 字數 1695 閱讀 6835

題目:

有n種物品和乙個容量為v的揹包,每種物品都有無限件可用。放入第i種物品的費用是ci,價值是wi,求解:將哪些物品裝入揹包,可使這些物品耗費的費用和不超過揹包容量,且價值總和最大。

分析:(一)建立狀態方程

可以轉化為01揹包問題求解

dp[i][v]表示前i件種物品放入容量為v的揹包的最大價值,則有:

dp[i][v]=max,其中0<=k*c[i]<=v,狀態方程的建立不難理解

(二)根據狀態方程實現**

有了狀態方程,看出i與i-1有關,所以i從1到n遍歷,v與v-k*c[i]有關,所以k從0到k*c[i]<=v遍歷

[cpp]view plain

copy

#include 

#include 

using namespace std;    

#define n 3//物品個數    

#define v 10//揹包容量    

int c[n+1]=;  //ci表示第i件物品的費用   (i從1開始)    

int w[n+1]=;   //w[i]表示第i件物品的價值    

int dp[n+1][v+1];  

int completepack()  

return dp[n][v];  

}  int main()    

(三)優化資料結構

注意到狀態方程中i只與i-1有關,可以消去一維,但是如果直接由上面的**消維是不成的,因為我們用到了上一狀態的v-k*c[i],也就是我們在進入下一狀態前,這一狀態的每乙個dp[v],0<=v<=v,必須都是已知的,但是以上**是對k進行遍歷,和v無關,所以要對v進行遍歷,那該如何寫呢?

從狀態方程中找線索,dp[i][v]=max,0<=k*c[i]<=v

我們再把它展開一下看,dp[i][v]=max

再來看我們需要的v,這個v範圍是0<=v<=v,將v的範圍帶入上式看,我們發現雖然v-c[i],v-2c[i]看起來很繁瑣,但是追根究底範圍也一定是在0到v之間,

再來看它們之間的關係,發現後乙個元素永遠比前乙個元素多了乙個w[i],如果我們事先將dp[v-c[i]]+w[i]的值得到,那麼當v增加乙個c[i]時,取dp[v-c[i]],這裡dp[v-c[i]]就是dp[v-c[i]]+w[i],然後再加上乙個w[i],即dp[v-c[i]]+w[i]不就是取得兩件i物品所獲得的價值了嗎!想到這,**就可以實現了:

[cpp]view plain

copy

#include 

#include 

using namespace std;    

#define n 3//物品個數    

#define v 10//揹包容量    

int c[n+1]=;  //ci表示第i件物品的費用   (i從1開始)    

int w[n+1]=;   //w[i]表示第i件物品的價值    

int dp[v+1];  

int completepack()  

return dp[v];  

}  int main()    

發現了嗎?**和01揹包問題就內層迴圈的順序不同而已,但是實際意義可是大不相同啊

(四)深入優化

如果再繼續優化也是可以的,如果有兩件物品i和j,有c[i]>c[j],w[i]

完全揹包 動態規劃

描述 直接說題意,完全揹包定義有n種物品和乙個容量為v的揹包,每種物品都有無限件可用。第i種物品的體積是c,價值是w。求解將哪些物品裝入揹包可使這些物品的體積總和不超過揹包容量,且價值總和最大。本題要求是揹包恰好裝滿揹包時,求出最大價值總和是多少。如果不能恰好裝滿揹包,輸出no輸入 第一行 n 表示...

動態規劃揹包問題 完全揹包

問題描述 有n種物品,每種均有無窮多個。第i個物品的體積為vi,重量為wi。選一些物品裝到容量為c的揹包中,使得揹包內物品在總體積不超過c的前提下重量盡量大。問題分析 開乙個陣列f i j 表示前i種物品中選取若干件物品放入剩餘空間為j的揹包中所能得到的最大重量。每種物品無窮個,所以還要有乙個k遍歷...

動態規劃 揹包問題 完全揹包

有n種物品和乙個容量為v的揹包,每種物品都有無限件可用。第i種物品的費用是w i 價值是v i 求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。貪心 y or n 因為每件物品都可以選取任意件,你也許會想到貪心演算法 選取價值最高的就好了 看上去沒什麼毛病,但是有乙個問題...