1315:集合的划分(来源信息学奥赛一本通)
【题目描述】
设S是一个具有n个元素的集合,S=〈a1,a2,……,an〉,现将S划分成k个满足下列条件的子集合S1,S2,……,Sk,且满足:
1.Si≠∅
2.Si∩Sj=∅ (1≤i,j≤k,i≠j)
3.S1∪S2∪S3∪…∪Sk=S
则称S1,S2,……,Sk是集合S的一个划分。它相当于把S集合中的n个元素a1,a2,……,an 放入k个(0<k≤n<30)无标号的盒子中,使得没有一个盒子为空。请你确定n个元素a1,a2,……,an 放入k个无标号盒子中去的划分数S(n,k)。
【输入】
给出n和k。
【输出】
n个元素a1,a2,……,an 放入k个无标号盒子中去的划分数S(n,k)。
【输入样例】
10 6
【输出样例】
22827
【题目解读】
题目的意思是要求n个数不重复的放入k个相同的盒子中且每个盒子不空有多少种方法,比如S={1,2,3,4},k=3可以做划分P1={1}|{2}|{3,4},P2={1}|{3}|{2,4}等等。
写这个题的目的是为了学习递归算法(哇真的不懂啊,小白很是懵懂)
先关注边界值(终止条件)
n<k || k=0,f(n,k)= 0,n小于k的话必定会出现空盒子;
n=k || k=1,f(n,k)=1,
因为递归是从后往前找,所以要有终止条件,也就是一定会出现上面两个情况
递归关系式(n>k)
情况1:有一个子集只有一个元素,也就是ai作为k个集合中的一个{ai},那么剩下n-1个元素分到k-1个集合中,也就是f(n-1,k-1)种;
情况2:不存在单个元素作为一个集合,也就是不存在{ai}这样的子集,那么剩下n-1个元素分到k个集合中,并且ai可以放到k个集合中任何一个构成一种新的划分Pi,那么就有k*f(n-1,k)种,比如有1,2,3三个集合,ai可以分别放到三个集合中,组成3种划分方式;
所以我们包含这两种情况得出递归关系式,f(n,k)=f(n-1,k-1)+k*f(n-1,k),因为是递归算法,所以我们的思路就是要向前找与n,k相邻的一个关系写出递归关系式和终止条件
最终我们就写出以下的递归函数:
long long f(int n,int k) //这里就记住一般没有模运算的递归都会开long long
{
if (n < k || k == 0) return 0;
if (n == k || k == 1) return 1; //这两行是递归的终止条件
return f(n - 1, k - 1) + k * f(n - 1, k); //这里返回的是递归关系式
}
最终也是三行代码让我感受人间差距。