0-1背包问题——动态规划

 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 }

原文地址:https://www.cnblogs.com/jieforever/p/4696548.html