問題描述:有n
件物品和乙個容量為c
的揹包。第i件物品的價值是v[i],重量是w[i]。求解將哪些物品裝入揹包可使價值總和最大。所謂01揹包,表示每乙個物品只有乙個,要麼裝入,要麼不裝入。
今天下午的演算法複習課,老師提的各種演算法經典問題時,出現頻率就是01揹包問題了!動態規劃、回溯法、分支限界法,在貪心演算法時也提到注意揹包問題,當然01揹包問題不能用貪心演算法實現,不能保證能得到最優解。回溯法是最近學的,所以試著用c語言將其實現了下,下面作以分析,後期將會繼續用其他兩種演算法實現01揹包問題,並做比較。
回溯法:01揹包屬於找最優解問題,用回溯法需要構造解的子集樹。在搜尋狀態空間樹時,只要左子節點是可乙個可行結點,搜尋就進入其左子樹。對於右子樹時,先計算上界函式,以判斷是否將其減去,剪枝啦啦!
上界函式bound():當前價值cw+剩餘容量可容納的最大價值<=當前最優價值bestp。
為了更好地計算和運用上界函式剪枝,選擇先將物品按照其單位重量價值從大到小排序,此後就按照順序考慮各個物品。
下面直接貼**吧:
#include
#include
int n;//物品數量
double c;//揹包容量
double v[100];//各個物品的價值
double w[100];//各個物品的重量
double cw = 0.0;//當前揹包重量
double cp = 0.0;//當前揹包中物品價值
double bestp = 0.0;//當前最優價值
double perp[100];//單位物品價值排序後
int order[100];//物品編號
int put[100];//設定是否裝入
//按單位價值排序
void knapsack()
if(cw+w[i]<=c)
if(bound(i+1)>bestp)//符合條件搜尋右子數
backtrack(i+1);
}//計算上界函式
double bound(int i)
if(i<=n)
b+=v[i]/w[i]*leftw;
returnb;
}int main()
knapsack();
backtrack(1);
printf("最有價值為:%lf\n",bestp);
printf("需要裝入的物品編號是:");
for(i=1;i<=n;i++)
return0;
}執行結果截圖:
演算法複雜度分析:上界函式bound()需要o(n)時間,在最壞的情況下有o(2^n)個右子結點需要計算上界,回溯演算法backtrack需要的計算時間為o(n2^n)。
回溯演算法 0 1揹包問題
給定乙個物品集合s 1,2,3,n 物品i的重量是wi,其價值是vi,揹包的容量為w,即最大載重量不超過w。在限定的總重量w內,我們如何選擇物品,才能使得物品的總價值最大。0 1揹包問題回溯演算法的資料結構 define num 100 int c 揹包的容量 int n 物品的數量 int cw ...
回溯演算法 01揹包問題
假期 2020.01 200 1揹包問題一般描述為 給定n種物品和乙個揹包。物品i的重量是w i 其價值為v i 揹包的容量為c。問應該如何選擇裝入揹包的物品,使得裝入揹包中的物品的總價值最大?注 每個物品只能使用一次。這次分析01揹包問題,採用回溯的方法實現。簡單的來說,回溯就是採用dfs然後加上...
0 1揹包問題,回溯實現
0 1揹包 問題描述,noip 2001 裝箱問題 有乙個箱子容量為 v 正整數,0 v 20000 同時有 n個物品 0 n 30,每個物品有乙個體積 正整數 要求n 個物品中,任取若干個裝入箱內,使箱子的剩餘空間為最小。動態規劃考慮 容量為v的箱子,最多能裝多少單位體積的物品vmax,v vma...