web-dev-qa-db-ja.com

n個の要素を持つセットのk個のサブセットへの分割数を数える

このプログラムは、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; 
} 
8
user10796621

countPを呼び出すたびに、セット内の1つの要素が暗黙的に考慮され、それを呼び出すことができます[〜#〜] a [〜#〜]

countP(n-1, k-1)項は、[〜#〜] a [〜#〜]が単独でセットに含まれている場合に由来します。この場合、[〜#〜] a [〜#なので、他のすべての要素(N-1)を(K-1)サブセットに分割する方法がいくつあるかを数える必要があります。 〜]はそれ自体で1つのサブセットを使用します。

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}
_

2番目のケースk*countP(n-1, k)は、以下のケースを示します。

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

または:

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

あなたが言及したのは 第2種のスターリング数 で、n個のオブジェクトのセットをk個の空でないサブセットに分割して enter image description here または enter 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];
}
4
aminography

countP(n,k)を取得するにはどうすればよいですか?以前の_n-1_要素を特定の数のパーティションに分割し、現在はn番目の要素があり、kパーティションを作成するとします。

これには2つのオプションがあります。

どちらか

  1. 以前の_n-1_要素をk部分に分割しました(これにはcountP(n-1, k)の方法があります)。このn番目の要素をこれらの部分の1つに挿入します( kの選択肢があります)。したがって、k*countP(n-1, k)があります。

または:

  1. 以前の_n-1_要素を_k-1_パーティションに分割します(これにはcountP(n-1, k-1);の方法があります)。そして、n番目の要素をkパーティション(選択肢は1つだけです:別に置く)。したがって、countP(n-1, k-1);があります。

したがって、それらを合計して結果を取得します。

4
ZhaoGang

に基づく This セットのパーティションは、セットの要素を空ではないサブセットにグループ化したもので、すべての要素がサブセットの1つだけに含まれるようになっています。したがって、n要素セットのパーティションの総数は ベル番号 であり、次のように計算されます。 ベル番号式 したがって、式を再帰的に変換する場合関数は次のようになります:k * countP(n-1、k)+ countP(n-1、k-1);

2
Alireza.N