0-1背包回溯

Posted lolybj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了0-1背包回溯相关的知识,希望对你有一定的参考价值。

限定条件:

如果放入该物品<剩余背包容量则回溯。

如果当前价值+剩余容量下剩余物品的最大价值<当前最大价值则回溯。(剩下在怎么放都不会比当前最大价值大,就没必要算了)

测试:

第一行分别输入物品数量n与背包容量c

用例:

10 300
95 89
75 59
23 19
73 43
50 100
22 72
6 44
57 16
89 7
98 64

测试结果:

388

代码:

 1 /*测试用例结果388 
 2 10 300
 3 95 89
 4 75 59
 5 23 19
 6 73 43
 7 50 100
 8 22 72
 9 6 44
10 57 16
11 89 7
12 98 64
13 */ 
14 #include<stdio.h>
15 #include<stdlib.h>
16 int n,c;//物品数量,背包容量 
17 int w[300],v[300]; //物品重量,物品价值。 
18 float u[300][2];
19 float U[300];//物品单位价值。 
20 int max = 0; //当前最大价值 
21 int num = 0;//递归次数 
22 int cmp(const void *a,const void *b){//排序从大到小 
23     return ((float*)a)[1]>((float*)b)[1]?-1:1;
24 }
25 float f1(int i,int weight);//返回剩余最大价值 
26 void f(int i,int weight,int val);//求最大价值 
27 int main(){
28     scanf("%d %d",&n,&c);
29     int w1[300],v1[300];
30     for(int i=0;i<n;i++){//输入每个物品质量与价值 
31         scanf("%d",&w1[i]);
32         scanf("%d",&v1[i]);
33     }
34     for(int i=0;i<n;i++){//获得单位价值 
35         u[i][0] = i;
36         u[i][1] = (float)v1[i]/w1[i];
37     }
38     qsort(u,n,sizeof(u[0]),cmp);//单位价值排序 
39     for(int i=0;i<n;i++){//排序物品 
40         w[i] = w1[(int)u[i][0]];
41         v[i] = v1[(int)u[i][0]];
42         U[i] =  u[i][1];
43     }
44     f(0,0,0);
45     printf("%d
",max);
46     printf("递归次数:%d",num);
47 }
48 void f(int i,int weight,int val){//i表示第i个物品,weight表示当前重量,val表示当前价值。 
49     num++;
50     if(i==n){//判断到第n个物品 
51         if(weight<=c) max = max>val?max:val;//返回当前价值和最大价值的最大者。 
52         return;
53     }
54     //右子树的进入条件 即放入当前物品 
55     //if(weight+w[i]<=c&&f1(i,c-weight)+val>max)//当剩余背包容量不足,或者当前价值+当前剩余最大价值<当前最大值,减去右子树。 
56         f(i+1,weight+w[i],val+v[i]);
57     //不放入当前物品 
58     f(i+1,weight,val);
59 }  
60 float f1(int i,int weight){//剩余最大价值。 
61     float sum = 0;
62     while(weight>=w[i]&&i<n){
63         sum += v[i];
64         weight -= w[i];
65         i++;
66     }
67     if(i<n&&weight>0){
68         sum += weight*U[i];        
69     }
70     return sum;
71 } 

运行结果:

 

 

 

技术分享图片

不剪枝递归次数:

 

技术分享图片

不考第一个约束条件递归次数:

技术分享图片

不考虑第二个约束条件:

技术分享图片

考虑所有约束条件先放进去:

技术分享图片

考虑所有约束条件先不放进去:

技术分享图片

可以看出剪枝越多效率越高。且同样约束条件下先放与不先放递归次数不同。一般先放递归次数少效率高。











以上是关于0-1背包回溯的主要内容,如果未能解决你的问题,请参考以下文章

用回溯法做0-1背包问题,这两行(程序中标注)是干嘛?为啥又要减?

0-1背包问题如下,画用回溯法求解时的搜索情况,急用啊

0-1背包回溯

0-1背包问题(回溯法)

0-1背包问题(回溯法)

0-1背包问题(回溯法)