ybt1315 递归例题(虽然没用递归)集合划分
Posted wild-donkey
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ybt1315 递归例题(虽然没用递归)集合划分相关的知识,希望对你有一定的参考价值。
ybt1315 集合划分
递归算法
【题目描述】
设S是一个具有n个元素的集合,S=?a1,a2,……,an?S=?a1,a2,……,an?,现将S划分成k个满足下列条件的子集合S1,S2,……,SkS1,S2,……,Sk ,且满足:
1.Si≠?Si≠?
2.Si∩Sj=?Si∩Sj=? (1≤i,j≤k,i≠j1≤i,j≤k,i≠j)
3.S1∪S2∪S3∪…∪Sk=SS1∪S2∪S3∪…∪Sk=S
则称S1,S2,……,SkS1,S2,……,Sk是集合S的一个划分。它相当于把S集合中的n个元素a1,a2,……,ana1,a2,……,an 放入kk个(0<k≤n<300<k≤n<30)无标号的盒子中,使得没有一个盒子为空。请你确定nn个元素a1,a2,……,ana1,a2,……,an 放入kk个无标号盒子中去的划分数S(n,k)S(n,k)。
【输入】
给出nn和kk。
【输出】
nn个元素a1,a2,……,ana1,a2,……,an 放入kk个无标号盒子中去的划分数S(n,k)S(n,k)。
【输入样例】
10 6
【输出样例】
22827
设f~i,j~为i个元素时分成j个集合的方案数。
对任意的n,当满足k=n的时候,则f~n,k~=1。
分析除特殊情况外的一般情况f~4,,3~=6,则是由:
方案一:1,2;3;4
方案二:1;2,3;4
方案三:1;2;3,4
方案四:1,3;2;4
方案五:1,4;2;3
方案六:2,4;1;3
组成的。
可以将其理解为f~3,3~的情况往里加了元素4。
这样4就有两种情况,自己成为独立的集合(方案一,二,四);加入之前的集合(方案三,五,六)
(和ybt1192放苹果类似)
分这两类讨论:
如果新元素自己成为集合,那么就简化成讨论剩下i-1个元素分到j-1个集合的方案
如果新元素加入原有集合,那么就简化为讨论剩下i-1个元素分到原有j个集合的方案
但是新元素可以加入原有j个集合中任意一个,所以要乘j。
写出方程:f~i,j~=f~i-1,j-1~+j*f~i-1,j~
#include<iostream>
using namespace std;
long long n,k,f[505][505];
int main() {
cin>>n>>k;
for(int i=1;i<=n;i++) {
f[i][i]=1;
f[i][1]=1;
}
for(int i=2;i<=n;i++)
for(int j=2;j<i;j++) {
f[i][j]=f[i-1][j-1]+j*f[i-1][j];
}
cout<<f[n][k]<<endl;
return 0;
}
当然,也可以用滚动数组优化成一维数组:
#include<iostream>
using namespace std;
long long n,k,f[505];
int main() {
cin>>n>>k;
for(int i=1;i<=n;i++) {
f[i]=1;
}
for(int i=2;i<=n;i++)
for(int j=i-1;j>=2;j--) {//因为更新f[j]时要调用f[j-1],为了消除本轮数据造成的影响,需要倒着循环
f[j]=f[j-1]+j*f[j];
}
cout<<f[k]<<endl;
return 0;
}
(例题也好意思发博客)
以上是关于ybt1315 递归例题(虽然没用递归)集合划分的主要内容,如果未能解决你的问题,请参考以下文章