解01背包问题有很多种方法,就我知道的就有动态规划,回溯法,分支界限法这几种,下面就列出我的回溯法解法,以供参考 #include<iostream> #include <algorithm> using namespace std; class Knap { public: Knap(double *pp,double *ww,double cc,int nn)//构造函数 { p=pp; w=ww; c=cc; n=nn; cw=0; cp=0; bestp=0; x=new int[n+1]; bestx=new int[n+1]; } double knapsack();//找最优值的函数。 double Bound(int i);//边界函数 void BackTrack(int i);//回溯函数 void output()//输出最佳路径 { for(int i=1;i<=n;i++) cout<<bestx[i]<<" "; cout<<endl; } private: double c; int n; double *w; double *p; double cw; double cp; double bestp; int *x; int *bestx; }; void Knap::BackTrack(int i) { if(i>n) { if(cp>bestp)/*保证最优,这样下面的bestx就是最优的路径。*/ { bestp=cp; for(int i=1;i<=n;i++) bestx[i]=x[i]; } return; } if(cw+w[i]<=c)//left { x[i]=1;//记录进入坐子树 cw+=w[i]; cp+=p[i]; BackTrack(i+1); cw-=w[i]; cp-=p[i]; } if(Bound(i+1)>bestp)//right { x[i]=0;//记录进入右子树 BackTrack(i+1); } } class Object { public: int ID; double d; }; int cmp(Object a,Object b)//定于排序类型。 { return a.d>b.d;//降序 } double Knap::Bound(int i) { Object *Q=new Object[n+1]; int j; for(j=1;j<=n;j++) { Q[j].ID=j; Q[j].d=1.0*p[j]/w[j]; } sort(Q+1,Q+n+1,cmp);/*对数组Q排序。按cmp()方式排序。这里要注意是从Q[1]开始而不是从Q开始*/ /* for(j=1;j<=n;j++) cout<<Q[j].ID<<" "; cout<<endl; */ double cleft=c-cw; double b=cp; while(i<=n&&w[Q[i].ID]<=cleft) { cleft-=w[Q[i].ID]; b+=p[Q[i].ID]; i++; } if(i<=n) b+=1.0*p[Q[i].ID]*cleft/w[Q[i].ID];/*如果不能完整装入一个物品,则可以装入部分。*/ return b; } double Knap::knapsack() { /*分支判断,如果背包容量足够大,就不用再回溯搜索了。*/ int i; double W=0; double P=0; for(i=1;i<=n;i++) { W+=w[i]; P+=p[i]; } if(W<=c) return P; /*如果背包容量不够大,则有最有的方案,使用回溯方法。*/ BackTrack(1); return bestp; } int main() { int n=4; double c=7;//背包容量 /*注意点,这里的数组p[]和w[]的第一个元素是-1,这是因为我在操作过程中都是从数组元素的1开始的,而我们知道数组中第一个元素是0号元素,所以我这里用-1填上*/ double p[]={-1,9,10,7,4};//物品价值 double w[]={-1,3,5,2,1};//物品重量 Knap k=Knap(p,w,c,n); cout<<k.knapsack()<<endl; k.output(); cout<<k.Bound(1)<<endl;//输出为22,是最大理想值 return 1; }