集合划分(递归算法)

问题描述
n个元素的集合{1,2,3, …,n }可以划分为若干个非空子集。
例如,当n=4 时,集合{1,2,3,4}可以划分为15 个不同的非空子集如下:
{{1},{2},{3},{4}},
{{1,2},{3},{4}},
{{1,3},{2},{4}},
{{1,4},{2},{3}},
{{2,3},{1},{4}},
{{2,4},{1},{3}},
{{3,4},{1},{2}},
{{1,2},{3,4}},
{{1,3},{2,4}},
{{1,4},{2,3}},
{{1,2,3},{4}},
{{1,2,4},{3}},
{{1,3,4},{2}},
{{2,3,4},{1}},
{{1,2,3,4}}
给定正整数n,计算出n个元素的集合{1,2,3, … ,n }可以划分为多少个不同的非空子集。

其中设q(n,m)表示n个数可以表示为m个非空子集
根据m和n的关系,可以分为以下情况:

第一种情况
n=1时,只有一个元素,所以只能拆分为一个子集和;

第二种情况
m=1时,只能拆分为一个子集和就是他自己;

第三种情况
m=0或者n=0时,毫无疑问返回0;

第四种情况
m>n时,拆分的子集和数大于元素数,因为不能拆分为空集,所以这种情况没法拆分,所以return 0;

第五种情况
m=n时,元素数等于子集和的数,所以为1;

第六种情况
n>m时,也是最普遍的情况,这个可以划分为两种情况:
第一个是,将n个数中选出一个划分为一个集合则剩下n-1个数拆分成m-1个集合,即q(n,m)=q(n-1,m-1)
第二个是,将n-1个数拆分成m个集合,然后最后一个数放到这m个集合中的一个,也就是有m个情况,所以q(n,m)=m*q(n-1,m)
所以第六种情况为q(n-1,m-1)+m*q(n-1,m)

#include<stdio.h>
int q(int n,int m){//n个数分成m个非空集合
	if(n==1) return 1;
	if(m>n||m==0) return 0;
	if(m==1||n==m) return 1;
	if(n>m) return (q(n-1,m-1)+m*q(n-1,m));
}
int main(){
	int n;int count=0;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		count+=q(n,i);
	} 
	printf("可以划分为%d个集合",count);
	return 0;
} 

与该问题相似的问题可以顺便练练手:
整数拆分问题

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值