回溯——0-1背包问题

来源:互联网 发布:ext json 编辑:程序博客网 时间:2024/06/07 05:08
1、算法描述
   0-1背包问题时子集选取问题。0-1背包问题的解空间可用子集树表示。集0-1背包问题的回溯法与装载问题的回溯法十分相似。在搜索解空间树时,只要其左儿子结点是一个可行结点,搜索就进入其左子树。当右子树中可能包含最优解时才进入右子树搜索。否则将右子树剪去。设r是当前剩余物品价值总和;cp是当前价值,bestp是当前最优价值。当cp+r<<bestp时,可剪去右子树。计算右子树中解的上界的更好方法是将剩余物品依其单位价值排序,然后依次装入物品,直至装不下时,再装入该物品的一部分而装满背包。由此得到的价值是右子树中解的上界。
 
#include <stdio.h>#include <stdlib.h>#include <algorithm>using namespace std;template <class Typew,class Typep>class Knap {public :Typep Bound(int i);void Backtrack(int i);Typew c;//背包容量int n;//物品数int *bestx;//记录当前最优装载Typew *w;//物品重量数组Typep *p;//物品价值数组Typep cp;//当前价值Typew cw;//当前重量Typep bestp;//当前最优价值};template<class Typew,class Typep>void Knap<Typew,Typep>::Backtrack(int i){if(i>n) {//达到叶子节点bestp=cp;for(int j=1;j<=n;j++)printf("%d ",bestx[j]);printf("\n");return ;}if(cw+w[i]<=c) //进入左子树{bestx[i]=1;cw+=w[i];cp+=p[i];Backtrack(i+1);cw-=w[i];cp-=p[i];}if(Bound(i+1)>bestp)//进入右子树{Backtrack(i+1);bestx[i]=0;}}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 Knapspack(int *,int *,int ,int);public :int operator<=(Object a)const{return (d>=a.d);}public:int ID;float d;};bool cmp(Object A,Object B){if(B.d<=A.d)return true;elsereturn false;}template<class Typew,class Typep>Typep Knapstack(Typep p[],Typew w[],Typew c,int n){//为Knap::Backtrack初始化Typew W=0;Typep P=0;Object * Q = new Object[n];for(int i=1;i<=n;i++){Q[i-1].ID=i;Q[i-1].d=1.0*p[i]/w[i];P+=p[i];W+=w[i];}if(W<=c)return P;//装入所有物品//依物品单位重量价值排序sort(Q,Q+n,cmp);//for(int j=1;j<=n;j++)//printf("%f ",Q[j-1].d);Knap<Typew,Typep> K;K.bestx = new int[n+1];for(int j=0;j<=n;j++)K.bestx[j]=0;K.p = new Typep[n+1];K.w = new Typew[n+1];for(int 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.c = c;K.n = n;K.bestp = 0;//回溯搜索K.Backtrack(1);delete[] Q;delete[] K.w;delete[] K.p;return K.bestp;}void main(){int p[]={0,9,10,7,4};int w[]={0,3,5,2,1};int n=4;int c=7;int sum;sum=Knapstack(p,w,c,n);printf("%d \n",sum);system("pause");}

原创粉丝点击