1 // 动态规划法解决0-1背包问题 2 //example: 3 //物品种类n=5,背包容量c=10, 4 //物品的重量向量 w={2,2,6,5,4},物品的价值向量 v={6,3,5,4,6} 5 // O(min{n*c,2^n}) 6 #include "stdafx.h" 7 #include <cstdlib> 8 #include <iostream> 9 10 using namespace std; 11 template<class Type> 12 Type Knapsack(int n,Type c,Type v[],Type w[],Type**p,int x[]) 13 { 14 int* head=new int[n+2]; 15 head[n+1]=0;p[0][0]=0;p[0][1]=0; 16 int left=0,right=0,next=1; 17 head[n]=1; 18 for(int i=n;i>=1;i--){ 19 int k=left; 20 for(int j=left;j<=right;j++){ 21 if(p[j][0]+w[i]>c) break; 22 Type y=p[j][0]+w[i],m=p[j][1]+v[i]; 23 while(k<=right&&p[k][0]<y){ 24 p[next][0]=p[k][0]; 25 p[next++][1]=p[k++][1]; 26 } 27 if(k<=right&&p[k][0]==y){ 28 if(m<p[k][1]) m=p[k][1]; 29 k++; 30 } 31 if(m>p[next-1][1]) {p[next][0]=y;p[next++][1]=m;} 32 while(k<=right&&p[k][1]<=p[next-1][1]) k++; 33 34 } 35 while(k<=right){p[next][0]=p[k][0];p[next++][1]=p[k++][1]; } 36 left=right+1;right=next-1;head[i-1]=next; 37 } 38 Traceback(n,w,v,p,head,x); 39 return p[next-1][1]; 40 41 } 42 43 template<class Type> 44 void Traceback(int n,Type w[],Type v[],Type**p,int* head,int x[]){ 45 std::cout<<"物品清单如下:(‘0’表示没有,‘1’表示有)"<<endl; 46 Type j=p[head[0]-1][0],m=p[head[0]-1][1]; 47 for(int i=1;i<=n;i++) 48 { 49 x[i]=0; 50 for(int k=head[i+1];k<=head[i]-1;k++){ 51 if(p[k][0]+w[i]==j&&p[k][1]+v[i]==m){ 52 x[i]=1;j=p[k][0];m=p[k][1];break; 53 } 54 } 55 56 std::cout<<"第"<<i<<"中物品的状态为:"; 57 std::cout<<x[i]<<endl; 58 } 59 60 } 61 62 63 64 int main(int argc, char *argv[]) 65 { 66 67 int w[]={10002,2,2,6,5,4},v[]={1,6,3,5,4,6}; //w和v的首零元素不计入0-1背包问题求解中 68 //int w[]={1002,4,5,6,2,2},v[]={8,6,4,5,3,6}; 69 //cout<<w[3]<<v[3]<<endl; 70 int n=5,c=10; 71 int x[6]={0}; 72 int** p=new int*[n+100];//数组必须足够大,next可能远大于n 73 for(int i=0;i<=n+100;i++) p[i]=new int[2]; 74 cout<<"最优背包的解为:"<<endl; 75 int y=Knapsack(n,c,v,w,p,x); 76 77 cout<<"最大价值:"<<y<<endl; 78 79 return 0; 80 }