- UID
- 2
- 精华
- 积分
- 7736
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
这几天学回溯法,稍微有点心得了,其实就是按深度优先遍历问题解树,而分支界限法则是按广度优先遍历
给定n=4 W={11,13,24,7} M=31 则子集合数问题的解为X={0,0,1,1} 和X={1,1,0,1}
X只能取{0 1},相应地是选或者不选该数,按照选和不选,就可以构造一颗解树,利用回溯法遍历该树。
复杂度本应该是O(2^n) 但是由于分支裁剪以后,下面的子树都不用遍历了,所以复杂度应该远小于这个
下面是我的代码:
- // sumofsub.cpp : Defines the entry point for the console application.
- //
- #include <stdio.h>
- int main(int argc, char* argv[])
- {
- int arr[6]={5,10,12,13,15,18};
- int x[6]={0,0,0,0,0,0};//0:左子树没走过 1:左子树走过,右子树没走过 2:左子树走过,右子树走过
- int sum=30;
- int totalsum=0;
- int n=6;
- for(int i=0;i<n;i++)
- {
- totalsum+=arr[i];
- }
- int layer=0;
- while(layer>=0)
- {
- if(totalsum >= sum)
- {
- if(arr[layer] == sum)
- {
- for(int i=0;i<layer;i++)
- {
- if(x[i] == 1)
- printf("%d ",arr[i]);
- }
- printf("%d\n",arr[layer]);
- x[layer]=2;
- }
- else if(arr[layer] < sum && x[layer] != 2)
- {//走左子树
- if(x[layer] == 0)//如果左子树没走过,走左子树
- {
- x[layer]=1;
- sum -= arr[layer];
- }
- else
- {
- x[layer]=2;
- x[layer+1]=0;
- }
- totalsum -= arr[layer];
- layer++;
- continue;
- }
- else
- {
- x[layer]=2;
- }
- }
- else
- {
- x[layer]=2;
- }
- if(x[layer] == 2)
- {
- //向上层回溯
- layer--;
- if(layer>=0)
- {
- if(x[layer] < 2)
- sum += arr[layer];
- totalsum += arr[layer];
- }
- }
- }
- getchar();
- return 0;
- }
复制代码 |
|