题目
集合划分:
给一个有 n 个元素的集合,将它划分为多个非空子集(可以包含自己),问有多少种划分?
样例输入
4
样例输出
15
样例解释
输入为 n ,表示集合有n个元素
输出为15 ,表示有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 元素划分,可以划分为1~ n 组。
- 如果划分为1组,那一个组就有 n 个元素;
- …
- 如果划分为 n 组,那么每组就是一个元素。
如果我们能设计出将 n 元素划分为 m 组的函数f(n,m)
,外面嵌套一个对 m 的 for 循环就可以了。
- 假设将一个 n 元素划分为一个 m 组:
(1)如果 n = 1 ,说明只有一个元素,则只能划分为一个组
(2)如果 m = 1 ,说明划分为1组,则也只有一种划分。
(3)如果 n = m ,将 n 个元素划分为 n 组,肯定也只有一种划分。
(4)else:这里可以采用分治递归的方式解决:
”将 n 个元素划分为 m 组 “可以分成下面两种情况:
①如果第 n 号元素被单独分为了一组,那接下来就是需要将1~ n-1 个元素划分为 m-1 组。f(n,m)=f(n-1,m-1)
②如果第 n 号元素没有被单独分为了一组,接下来就是需要把 1~ n-1 个元素划分为 m 组,把 n 号元素插入到 m 组中的其中一组中去。f(n,m)=m*f(n-1,m)
AC代码
#include<iostream>
using namespace std;
long f(int n,int i) {//将n个数划分为i组 会有多少种划分??
if(i==1||n==i)//如果划分为n组 或者划分为1组 则均只有一种划分
return 1;
return f(n-1,i-1)+i*f(n-1,i);
//将n号元素单独为一组,剩下1~n-1个元素为i-1组
//不将n个元素单独为一组:
//将1~n-1个元素分为i组,将n号元素插入到其中某一组中去,
//插到哪组呢?有i种插法,因此需要乘i
}
int main() {
int n,sum=0;
cin>>n;
for(int i=1; i<=n; i++)
sum+=f(n,i);
cout<<sum;
}