第二部分 基础算法 --第四章 递归算法1315:【例4.5】集合的划分

1315:【例4.5】集合的划分

时间限制: 1000 ms 内存限制: 65536 KB
提交数: 8438 通过数: 3559
【题目描述】
设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


思路:

{an}是k子集合中的一个,于是我们只要把a1,a2,an-1划分k-1个子集,划分的个数共有s(n-1,k-1)

{an}不是k个子集中的任意一个子集,则an必与其他元素构成一个子集,则问题相当于先把a1,a2,a3…an-1划分成k个子集,这 种情况下划分数共有s(n-1,k)个,然后在把an加入到k个子集中的任意一个中去,共有k种加入方式,这样对于an的每一种加入方式,都可以使集合划分为k个子集,因此根据乘法原理,划分数共有k*s(n-1,k)个

#include<iostream>
#include<cstring>
using namespace std;
long long s(int n,int k)
{
    if((n<k)||(k==0)) return 0;
    if((k==1)||(k==n)) return 1;
    return s(n-1,k-1)+k*s(n-1,k);
}
int main()
{
    int n,k;
    cin>>n>>k;
    cout<<s(n,k)<<endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章