[英]How to divide a set into K subsets such that the sum of the elements in the subsets are minimal?
[英]count number of partitions of a set with n elements into k subsets
該程序用於將具有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;
}
每個countP
調用都隱式地考慮集合中的單個元素,讓我們將其稱為A.
countP(n-1, k-1)
項來自A本身在集合中的情況。 在這種情況下,我們只需計算將所有其他元素(N-1)划分為(K-1)子集的方式,因為A本身占用一個子集。
然后, k*countP(n-1, k)
項來自A本身不在集合中的情況。 因此,我們計算出將所有其他(N-1)值划分為K個子集的方法的數量,並乘以K,因為我們可以添加A到K個可能的子集。
例如,考慮集合[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}
你提到的是第二類斯特林數,它列舉了將一組n個對象划分為k個非空子集的方法的數量,並用 要么 。
它的遞歸關系是:
對於初始條件為k > 0
:
。
使用動態編程計算它比遞歸方法更快:
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];
}
我們如何獲得countP(n,k)
? 假設我們已經將先前的n-1
元素划分為一定數量的partion,現在我們有第n個元素,並且我們嘗試進行k
分區。
我們有兩個選擇:
或
n-1
元素划分為k
部分(我們有countP(n-1, k)
這樣做的方式),並且我們將這個第n個元素放入這些部分中的一個(我們有k
選擇)。 所以我們有k*countP(n-1, k)
。 要么:
n-1
元素划分為k-1
分區(我們有countP(n-1, k-1);
這樣做的方法),我們將第n個元素作為單個部分來實現k
分區(我們只有一個選擇:單獨放置)。 所以我們有countP(n-1, k-1);
。 所以我們總結一下並得到結果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.