问题描述:
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;
}
与该问题相似的问题可以顺便练练手:
整数拆分问题