子集和问题

本文探讨了使用回溯法解决子集和问题的实现细节,并指出了求解全排列对于该问题的优势。文章还介绍了如何通过子集树解决此问题,提供了代码示例,最终总结了递归退出条件的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

                                                                                                                                                                                                              ----题目出自《计算机算法设计与分析  第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版》   王晓东

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值