将具有n个元素的集合的分区数计数为k个子集

时间:2018-12-16 06:22:37

标签: c++ algorithm combinatorics

该程序用于将具有n个元素的集合的分区数计数为k个子集,我在这里return k*countP(n-1, k) + countP(n-1, k-1);感到困惑 有人可以解释一下这里发生了什么吗? 为什么我们要乘以k?

注意->我知道这不是计算将成为DP的分区数量的最佳方法

// A C++ program to count number of partitions 
// of a set with n elements into k subsets 
#include<iostream> 
using namespace std; 

// Returns count of different partitions of n 
// elements in k subsets 
int countP(int n, int k) 
{ 
    // Base cases 
    if (n == 0 || k == 0 || k > n) 
        return 0; 
    if (k == 1 || k == n) 
        return 1; 

    // S(n+1, k) = k*S(n, k) + S(n, k-1) 
    return k*countP(n-1, k) + countP(n-1, k-1); 
} 

// Driver program 
int main() 
{ 
    cout << countP(3, 2); 
    return 0; 
} 

4 个答案:

答案 0 :(得分:4)

您提到的是Stirling numbers of the second kind,它列举了将n个对象集合划分为k个非空子集并用enter image description hereenter image description here表示的方法的数量。

它的递归关系是:

enter image description here

k > 0的初始条件:

enter image description here

使用动态编程来计算它比使用递归方法更快:

int secondKindStirlingNumber(int n, int k) {

    int sf[n + 1][n + 1];
    for (int i = 0; i < k; i++) {
        sf[i][i] = 1;
    }
    for (int i = 1; i < n + 1; i++) {
        for (int j = 1; j < k + 1; j++) {
            sf[i][j] = j * sf[i - 1][j] + sf[i - 1][j - 1];
        }
    }
    return sf[n][k];
}

答案 1 :(得分:3)

每个countP调用都隐式考虑了集合中的单个元素,将其称为 A

countP(n-1, k-1)一词来自 A 本身在集合中的情况。在这种情况下,我们只需要计算将所有其他元素(N-1)划分为(K-1)个子集有多少种方法,因为 A 本身占据了一个子集。

k*countP(n-1, k)术语来自于 A 在其自身集合中 not 的情况。因此,我们找出了将所有其他(N-1)个值划分为K个子集并乘以K的方法的数量,因为有K个可能的子集,我们可以添加 A

例如,将集合[A,B,C,D]K=2一起考虑。

第一种情况countP(n-1, k-1)描述了以下情况:

{A, BCD}

第二种情况k*countP(n-1, k)描述了以下情况:

2*({BC,D}, {BD,C}, {B,CD}) 

或者:

{ABC,D}, {ABD,C}, {AB,CD}, {BC,AD}, {BD,AC}, {B,ACD}

答案 2 :(得分:2)

我们如何获得countP(n,k)?假设我们已经将先前的n-1元素划分为一定数量的分区,现在我们有了第n个元素,并且尝试对k进行分区。

为此,我们有两个选择:

任一

  1. 我们已将先前的n-1元素划分为k个部分(我们有countP(n-1, k)种方式),并将第n个元素放入这些部分之一(我们有k个选择)。因此,我们有了k*countP(n-1, k)

或:

  1. 我们将先前的n-1元素划分为k-1分区(我们有countP(n-1, k-1);的方式),并且将第n个元素作为单个部分来实现{{1 }}分区(我们只有一种选择:将其分开放置)。因此,我们有了k

所以我们将它们总结并得到结果。

答案 3 :(得分:2)

This的基础上,集合的分区是将集合的元素分组为非空子集的方式,每个元素都包含在一个子集中,并且只有一个子集中。因此,n个元素集的分区总数为Bell number,其计算方式如下: Bell number formula 因此,如果要将公式转换为递归函数,它将类似于: k * countP(n-1,k)+ countP(n-1,k-1);