0-1背包回溯
还是先用到贪心:按单位重量价值由大到小排序
限界函数:假定可以装入部分,算出把背包装满的价值,作为上界
回溯函数:判断完这一层返回上一层
代码实现:
1 #include<iostream> 2 using namespace std; 3 int n;//物品数量 4 double c;//背包容量 5 double v[100];//各个物品的价值 6 double w[100];//各个物品的重量 7 double cw = 0.0;//当前背包重量 8 double cp = 0.0;//当前背包中物品价值 9 double bestp = 0.0;//当前最优价值 10 double perp[100];//单位物品价值排序后 11 int order[100];//物品编号 12 int put[100];//设置物品是否装入 解空间向量 13 14 //按单位价值排序 15 void knapsack() 16 { 17 int i,j; 18 int temporder = 0; 19 double temp = 0.0; 20 for(i = 1;i <= n;i++) 21 perp[i]=v[i]/w[i]; 22 for(i = 1;i<=n-1;i++) 23 { 24 for(j=i+1;j<=n;j++) 25 { 26 if(perp[i]<perp[j])//冒泡排序 27 { 28 temp = perp[i]; 29 perp[i] = perp[j]; 30 perp[j] = temp; 31 32 temporder = order[i]; 33 order[i] = order[j]; 34 order[j] = temporder; 35 36 temp = v[i]; 37 v[i] = v[j]; 38 v[j] = temp; 39 40 temp = w[i]; 41 w[i] = w[j]; 42 w[j] = temp; 43 } 44 } 45 } 46 } 47 48 //回溯函数 49 void backtrack(int i) 50 { 51 double bound(int i); 52 if(i>n)//到达最后一层,找到一个可行的解 53 { 54 bestp = cp; 55 return; 56 } 57 if(cw+w[i]<=c)//当前背包重量加上要放入的物品重量小于等于背包容量 58 { 59 cw+=w[i]; 60 cp+=v[i]; 61 put[i]=1; 62 backtrack(i+1); 63 cw-=w[i]; 64 cp-=v[i]; 65 } 66 if(bound(i+1)>bestp)//符合条件搜索右子树 67 backtrack(i+1); 68 } 69 70 //限界函数 71 double bound(int i) 72 { 73 double leftw = c-cw; 74 double b = cp; 75 while(i<=n&&w[i]<=leftw) 76 { 77 leftw-=w[i]; 78 b+=v[i]; 79 i++; 80 } 81 if(i<=n) 82 b+=v[i]/w[i]*leftw; 83 return b; 84 } 85 86 87 88 int main() 89 { 90 int i; 91 cout<<"请输入物品的数量和背包的容量:"<<endl; 92 cin>>n>>c; 93 cout<<"请输入物品的重量和价值:"<<endl; 94 for(i = 1 ; i <= n ; i++){ 95 cout<<"第"<<i<<"个物品的重量:"<<endl; 96 cin>>w[i]; 97 cout<<"第"<<i<<"个物品的价值:"<<endl; 98 cin>>v[i]; 99 order[i]=i; 100 } 101 knapsack(); 102 backtrack(1); 103 cout<<"最大价值为:"<<bestp<<endl; 104 cout<<"需要装入的物品编号是:"<<endl; 105 for(i=1;i<=n;i++) 106 { 107 if(put[i]==1) 108 cout<<order[i]<<" "; 109 } 110 return 0; 111 }
posted on 2018-12-16 15:09 huangroumin 阅读(265) 评论(0) 收藏 举报