子集和问题
2012-03-02 20:39
225 查看
题目描述:子集和问题的一个实例为〈S,t〉。其中,S={ 1 x , 2 x ,…, n x }是一个正整数的集合,c是一个正整数。子集和问题判定是否存在S的一个子集S1,使得s1中的各元素之和等于c。
----题目出自《计算机算法设计与分析 第3版》 王晓东
思路:用回溯法解这道题,我本来想修改排列树使之可以求出一个集合的所有子集。但是分析了一下,时间复杂度比求全排列并没有多少减少。所以就直接求出全排列来解除此题。(想通了,求子集应该用子集树来解决)
注:这个题用子集树解更简单,时间复杂度更低。类似于0-1背包的回溯法。
代码如下:
总结:
1.遗留一个问题:如何求出一个集合的所有子集? 问题已经解决:用子集树来求解。这是一个很典型的子集树问题
2.加深了我对递归退出条件的逻辑顺序的理解。
参考资料:《计算机算法设计与分析 第3版》 王晓东
----题目出自《计算机算法设计与分析 第3版》 王晓东
思路:用回溯法解这道题,我本来想修改排列树使之可以求出一个集合的所有子集。但是分析了一下,时间复杂度比求全排列并没有多少减少。所以就直接求出全排列来解除此题。(想通了,求子集应该用子集树来解决)
注:这个题用子集树解更简单,时间复杂度更低。类似于0-1背包的回溯法。
代码如下:
#include <stdio.h> #include <conio.h> #define MAX 1000 //global variables int n=0;//the number of numbers int c=0;//the sum of the subset int num[MAX]={0}; int count=1;//the number of the element in a subset int result[MAX]={0}; //the answer of this question int c_sum=0;//current sum //prototypes void swap(int &a,int &b); void back_subset(int i); int main() { //declaration int i=0; printf("Please input the number of the numbers:"); scanf("%d",&n); printf("Please input the sum:"); scanf("%d",&c); for(i=1;i<=n;i++) scanf("%d",&num[i]); back_subset(1); getch(); } void back_subset(int i) { if(c_sum+num[i]==c) { result[count]=num[i]; for(int temp=1;temp<=count;temp++) printf("%d ",result[temp]); printf("\n\n\n\n----------separate line------------------\n\n\n\n"); return ; } if(i>n) return ; if(c_sum+num[i]>c) return; for(int j=i;j<=n;j++) { result[count++]=num[j]; c_sum+=num[j]; swap(num[i],num[j]); back_subset(i+1); swap(num[i],num[j]); c_sum-=num[j]; count--; } } void swap(int &a,int &b) { int temp=a; a=b; b=temp; }
总结:
1.遗留一个问题:如何求出一个集合的所有子集? 问题已经解决:用子集树来求解。这是一个很典型的子集树问题
2.加深了我对递归退出条件的逻辑顺序的理解。
参考资料:《计算机算法设计与分析 第3版》 王晓东