[英]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.