子集和问题

题目描述:子集和问题的一个实例为〈S,t〉。其中,S={ 1 x , 2 x ,…, n x }是一个正整数的集合,c是一个正整数。子集和问题判定是否存在S的一个子集S1,使得s1中的各元素之和等于c。

                                                                                                                                                                                                              ----题目出自《计算机算法设计与分析  第3版》 王晓东

        思路:用回溯法解这道题,我本来想修改排列树使之可以求出一个集合的所有子集。但是分析了一下,时间复杂度比求全排列并没有多少减少。所以就直接求出全排列来解除此题。(想通了,求子集应该用子集树来解决)

       注:这个题用子集树解更简单,时间复杂度更低。类似于0-1背包的回溯法。

        代码如下:

#include 
#include 
#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版》   王晓东

你可能感兴趣的:(算法和数据结构,回溯法)