有大牛總結了四種解法,自己要好好學習了。。。
需要全部裝滿嘛?
思路:如果採用暴力列舉每一件物品放進或者不放進揹包,每個物品都有兩種選擇,那就是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揹包問題的遞...