(疑)0 1揹包問題之動態規劃,遞迴

2021-09-19 04:57:29 字數 1793 閱讀 6974

有大牛總結了四種解法,自己要好好學習了。。。

需要全部裝滿嘛?

思路:如果採用暴力列舉每一件物品放進或者不放進揹包,每個物品都有兩種選擇,那就是2的n次方種,複雜度太大,

所以使用動態規劃方法:

注意:v是揹包剩餘可以裝的容量,v是揹包的總容量

有兩種情況

(1)不放進第i件物品,那麼就是前i-1件物品恰好裝入容量為v的揹包所獲得的最大值 ,也就是dp[i-1][v]

(2)   放第i件物品,那麼就是前i-1件物品恰好裝入容量為v-w[i]的揹包中所獲得的最大值,也就是dp[i-1][v-w[i]]+c[i]

所以狀態轉移方程為:dp[i][v]=max   (1<=i<=n,w[i]<=v<=v)  (小v表示揹包剩餘容量)

注意:因為dp[i][v]表示的恰好容量全部裝滿為v的時候,所以需要列舉dp[n][v](0=

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

}

滾動陣列:陣列優化

因為計算dp[i][v]時只需要dp[i-1][v]左側部分的資料,並且當計算dp[i+1]部分時,dp[i-1]的 資料又完全用不到了,只用到dp[i],所以可以開乙個一維陣列dp[v],列舉方向為i到n,v到v(逆序!!!),所以狀態轉移方程為:dp[v]=max(dp[v],dp[v-w[i]]+c[i])。

//滾動陣列

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

}

注意:如果採用二維陣列存放,v的列舉是順序還是逆序都可以;

如果使用一維陣列存放,v的列舉必須是逆序!!!

#include#includeusing namespace std;

const int maxn=100;//物品最大件數

const int maxv=1000;//物品最大容量

int w[maxn],c[maxn],dp[maxv];//這是陣列,用於存放單個物品重量,單個物品價值,最終答案最大價值

int main()

} //尋找dp[0......v]中最大的即為答案

int max=0;

for(int v;v<=v;v++)

} printf("%d\n",max);

return 0;

}

總結:動態規劃可以靈巧的避免重複計算:第 i 件物品放入或者不放入產生的最大值是完全可以前面 i-1 件物品的最大值來決定的,但是暴力列舉卻做不到。

方法二:遞迴解法

#include#include#includeusing namespace std;

int limitm;//限制的總重量

int option[100];//表示是否選擇這個物品,是的話為1.不是的話為0

int n;//物品種數

struct bag

num[100];//定義物品的結構體 ,用來表示每件物品的重量和價值

int find(int n, int m)//定義find方法,用來表示揹包所裝物品的最大價值

else

else

//當當前物品的重量小於揹包所剩重量的時候, 也是有兩種選擇,這件物品裝入揹包或者不裝入

else}}

}}int main()

cout<<"揹包所能承受的總重量:";

cin>>limitm;

cout<<"最佳裝填方案是:"

cout<<"總價值="

}

01揹包問題 遞迴 動態規劃求解

使用記憶化搜尋 存在重疊子問題 對於index,c這一資料對可能求解多次 int memo 用 0.index 的物品,填充容積為c的揹包的最大價值 param w 物體的重量 param v 物體的價值 param index 當前考慮的物體的index序列號 param c 當前所剩容量 ret...

動態規劃之01揹包問題

首先是問題描述 給定n種物品和一揹包,物品i的重量是wi,其價值是pi,揹包的容量是m,問如何選擇裝入揹包中的物品總價值最大?可以這樣理解 揹包的揹負有上限,因此在這個上限內盡可能多的裝東西,並且價值越多越好。在這裡我之想討論動態規劃解決這個問題的詳細過程。動態規劃是用空間換時間的一種方法的抽象。其...

動態規劃之0 1揹包問題

問題描述 現有n件物品和乙個容量為c的揹包。第i件物品的重量是重量為w i 價值是v i 已知對於一件物品必須選擇取 用1表示 或者不取 用0表示 且每件物品只能被取一次 這就是 0 1 的含義 求放置哪些物品進揹包,可使這些物品的重量總和不超過揹包容量,且價值總和最大。求解思路 0 1揹包問題的遞...