集合划分问题记录

今天上课做到了集合划分的问题,其实是一个比较基础的递归

N个元素的集合{1,2,…,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 },{3,2 }};      {{2,3,4},{1}};     {{1,3,4},{2}};

{{1,2, 4},{3}};      {{1,2,3},{4}};     {{1,2,3,4}};

给定正整数N,计算出N个元素的集合{1,2,…,N}可以划分多少个非空集合?

那么其实,本道题目最重要的就是找到其中的递归关系。首先其用更加具体的例子就是将n个球放到不限数量的盒子中一共有多少种算法。那么可以将问题分解为将n个球放到1个盒子中、放到2个盒子种、三个.......n个盒子中。其中用k来表示盒子的数量。当k==n或者k==1或者n==1的时候都只有一种情况,这样就找到了递归的边界值。那么当把n个球放到k个盒子之中时,可以将第n个球单独拿出分析。第一种情况是第n个球单独一个盒子,那么这种情况的可分个数就是将n-1个球放到k-1个盒子之中的个数。第二种情况就是将第n个球不单独放到一个盒子里去,也就是说,现有n-1个球放到k个盒子中的情况,然后把这个球放到k个盒子中的任意一个,也就是这种情况下共有k*f(n-1,k)个方法,因此得到递归方式和边界值,接下来进行递归就好了。

#include<iostream>
using namespace std;
int f(int n,int k)
{
	if(k==1 or n==k or n==1) return 1;
	if(k==0 or n<k or n==0) return 0;
	return f(n-1,k-1)+k*f(n-1,k);	
}

int main()
{
	int n = 4;
	int num=0;
	for(int i = 1;i<=n;i++)
	{
		num+=f(n,i);
		cout<<n<<"个数字分为"<<i<<"个集合一共有"<<f(n,i)<<"种情况"<<endl; 
	}
	cout<<n<<"的集合划分个数一共有"<<num<<"种情况"<<endl; 
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值