0-1揹包-回溯法

算法描述:ios

0-1揹包的回溯法,與裝載問題的回溯法十分類似。在搜索解空間樹時,只要其左兒子結點是一個可行結點,搜索就進入其左子樹。當右子樹中有可能包含最優解時才進入右子樹進行搜索。不然將右子樹剪去。算法

  計算右子樹上界的更好算法是:數組

    將剩餘物品依其單位重量價值排序,而後依次裝入物品,直至裝不下時,再裝入該物品的一部分而裝滿揹包。函數

算法實現:spa

  由Bound函數計算當前節點處的上界。code

  類Knap的數據成員記錄解空間樹的節點信息,以減小參數傳遞及遞歸調用所需的棧空間。blog

  在解空間樹的當前擴展結點處,僅當要進入右子樹時,才計算上界bound,以判斷是否可將右子樹剪去。排序

  進入左子樹時不須要計算上界,由於它與其父節點的上界相同。遞歸

算法實現:(代碼有點小問題,正在修改中)io

#include <iostream> #include <stdio.h> #include <stdlib.h>
using namespace std; template <class Typew,class Typep>
class Knap{ friend Typep Knapsack(Typep *,Typew *,Typew,int); private: Typep Bound(int i); void Backtrack(int i); Typew c;//揹包容量
                int n;//物品數
                Typew * w;//物品重量數組
                Typep * p;//物品價值數組
                Typew cw;//當前重量
                Typep cp;//當前價值
                Typep bestp;//當前最優價值
}; template <class Typew,class Typep>
void Knap<Typew,Typep>::Backtrack(int i) { if(i>n)//到達葉子
 { bestp = cp; return; } if(cw+w[i] <= c)//進入左子樹
 { cw += w[i]; cp += p[i]; Backtrack(i+1); cw -= w[i]; cp -= p[i]; } if(Bound(i+1)>bestp)//進入右子樹
                Backtrack(i+1); } template <class Typew,class Typep> Typep Knap<Typew,Typep>::Bound(int i)//計算上界
{ Typew cleft = c- cw;//剩餘容量
        Typep b = cp; while(i<=n && w[i]<=cleft)//以物品單位重量價值遞減序裝入物品
 { cleft -= w[i]; b += p[i]; i++; } //裝滿揹包
        if(i<=n) b+=p[i]*cleft/w[i]; return b; } class Object { friend int Knapsack(int *,int *,int,int); public: int operator <= (Object a)const { return (d >= a.d); } private: int ID; float d; }; int compare (const void * a, const void * b) { return ( *(int*)a - *(int*)b ); } template <class Typew,class Typep> Typep Knapsack(Typep p[],Typew w[],Typew c,int n) { int i; //初始化
        int W = 0; int P = 0; Object* Q = new Object[n]; for(i=0;i<n;i++) { // cout<<p[i]<<" "<<w[i]<<endl<<"-------------------------"<<endl;
                Q[i].ID = i; Q[i].d = 1.0*p[i]/w[i]; // cout<<Q[i].ID<<" "<<Q[i].d<<endl<<"----------------------"<<endl;
                P += p[i]; W += w[i]; // cout<<P<<" "<<W<<endl<<endl; 
 } if(W<=c) return P;//裝入全部物品 //依物品單位重量價值排序
        qsort (Q,n, sizeof(int), compare); Knap<Typew,Typep> K; K.p = new Typep [n+1]; K.w = new Typew [n+1]; for(i =1;i<=n;i++) { K.p[i] = p[Q[i-1].ID]; K.w[i] = w[Q[i-1].ID]; } K.cp = 0; K.cw = 0; K.n = n; K.bestp = 0; K.Backtrack(1); // cout<<K.bestp<<endl;
 delete [] Q; delete [] K.w; delete [] K.p; return K.bestp; } int main() { int p[4] = {9,10,7,4}; int w[4]= {3,5,2,1}; int num = Knapsack(p,w,7,4); cout<<num<<endl; return 0; }
相關文章
相關標籤/搜索