回溯——0/1背包问题 收藏


回溯算法的要点:

1,针对所给问题,定义问题的解空间。

2,确定容易搜索的解空间的组织结构。

3,通过剪枝优化搜索过程。

下面通过求解0/1背包问题来分析使用回溯算法的过程:

1,根据问题的描述,设所有的物件数是N,对应的重量和价值分别为w[0~N-1]和v[0~N-1],于是这个问题就转化成在这N件物件中选择一个子集,使其总价值最大,并且满足总重量不超过包的容量cw。因此此问题的解空间是2^n。

2,对于从n个元素的集合S中求满足某种性质的子集时,相应的子空间成为子集树,这类子集树通常是满完全二叉树,通过遍历这棵树的每个叶子节点来达到遍历整个解空间的目的,相应的时间复杂度为O(2^n)。

3,对于背包问题的剪枝函数,可以从以下两方面考虑:

(1)根据题目要求,选择物件的总重量不能超过包的容积,这可以作为一个剪枝条件。用Constraint(t)函数表示在遍历子集树第t层某个节点时,此约束函数是否满足,如不满足,则剪去相应的子树。

(2)第二种剪枝函数称为边界函数Bound(t),当它返回true时,表示当前遍历节点未取得最优值,需要进一步搜索子树。

view plaincopy to clipboardprint?
1 #include <stdio.h>  
 2 #define N 8 //所有物件的数量,也即是构成子集树的层次数  
 3 int w[N]={10,4,12,43,13,14,60,7};//weight  
 4 int v[N]={5,19,21,20,12,23,4,9};//value  
 5 int cw = 80;//current capacity ,and init is 80  
 6 int bestv = 0;//the bestv   
 7 int cv = 0;  
 8 int bestset[N];//get the choosen nodes  
 9 int x[N];//record current node's choice-state  
10 int rv;  
11   
12 void backtrack(int i)  
13 {  
14         if(i>N-1)  
15         {  
16                 if(cv > bestv)  
17                 {  
18                         bestv = cv;  
19                         int j =0;  
20                         //get the choosen nodes when one state is complete.(to the leaf of the tree)   
21                         for(j =0;j<i;j++)  
22                                 bestset[j]=x[j];  
23                 }  
24                 return;  
25         }  
26         rv -= v[i];  //current amount of left values  
27         if(w[i] <= cw && cv + rv <bestv)//满足约束条件,对于自集树,选择左孩子(1)。  
28         {  
29                 cw-=w[i];  
30                 cv = cv + v[i];  
31                 x[i] = 1;  
32                 backtrack(i+1);  
33                 cw += w[i];  
34                 cv -=v[i];  
35                 x[i] = 0;  
36         }  
37         //对于子集树,考虑右孩子(0)  
38         if(cv + rv < bestv)  
39         {  
40                 x[i] = 0;  
41                 backtrack(i+1);  
42         }  
43         rv +=v[i];  
44 }  
45 int main()  
46 {  
47         backtrack(0);  
48         printf("most v is %d/n",bestv);  
49         int i =0;  
50         printf("value is:");  
51         for(i =0;i<N;i++)  
52         {  
53                 rv += v[i];  
54         }  
55         for(i =0;i<N;i++)  
56         {  
57                 if(bestset[i] == 1)  
58                 printf(" %d",v[i]);  
59         }  
60         printf("/n");  
61 } 
 1 #include <stdio.h>
  2 #define N 8 //所有物件的数量,也即是构成子集树的层次数
  3 int w[N]={10,4,12,43,13,14,60,7};//weight
  4 int v[N]={5,19,21,20,12,23,4,9};//value
  5 int cw = 80;//current capacity ,and init is 80
  6 int bestv = 0;//the bestv
  7 int cv = 0;
  8 int bestset[N];//get the choosen nodes
  9 int x[N];//record current node's choice-state
 10 int rv;
 11
 12 void backtrack(int i)
 13 {
 14         if(i>N-1)
 15         {
 16                 if(cv > bestv)
 17                 {
 18                         bestv = cv;
 19                         int j =0;
 20                         //get the choosen nodes when one state is complete.(to the leaf of the tree)
 21                         for(j =0;j<i;j++)
 22                                 bestset[j]=x[j];
 23                 }
 24                 return;
 25         }
 26         rv -= v[i];  //current amount of left values
 27         if(w[i] <= cw && cv + rv <bestv)//满足约束条件,对于自集树,选择左孩子(1)。
 28         {
 29                 cw-=w[i];
 30                 cv = cv + v[i];
 31                 x[i] = 1;
 32                 backtrack(i+1);
 33                 cw += w[i];
 34                 cv -=v[i];
 35                 x[i] = 0;
 36         }
 37         //对于子集树,考虑右孩子(0)
 38         if(cv + rv < bestv)
 39         {
 40                 x[i] = 0;
 41                 backtrack(i+1);
 42         }
 43         rv +=v[i];
 44 }
 45 int main()
 46 {
 47         backtrack(0);
 48         printf("most v is %d/n",bestv);
 49         int i =0;
 50         printf("value is:");
 51         for(i =0;i<N;i++)
 52         {
 53                 rv += v[i];
 54         }
 55         for(i =0;i<N;i++)
 56         {
 57                 if(bestset[i] == 1)
 58                 printf(" %d",v[i]);
 59         }
 60         printf("/n");
 61 }
 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/clearriver/archive/2009/06/15/4271472.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值