Ce programme sert à compter le nombre de partitions d’un ensemble de n éléments dans k sous-ensembles. Je confond ici return k*countP(n-1, k) + countP(n-1, k-1);
Quelqu'un peut-il expliquer ce qui se passe ici? Pourquoi multiplions-nous avec k?
NOTE-> Je sais que ce n'est pas la meilleure façon de calculer le nombre de partitions qui seraient 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;
}
Vous avez mentionné les nombres Stirling du second type qui énumèrent le nombre de façons de partitionner un ensemble de n objets en k sous-ensembles non vides et désignés par ou .
Sa relation récursive est:
pour k > 0
avec les conditions initiales:
.
Le calculer à l'aide de la programmation dynamique est plus rapide que l'approche récursive:
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];
}
Chaque appel countP
considère implicitement un seul élément de l'ensemble, appelons-leA.
Le terme countP(n-1, k-1)
provient du cas oùAest dans un ensemble par lui-même. Dans ce cas, il suffit de compter le nombre de façons de partitionner tous les autres éléments (N-1) en (K-1) sous-ensembles, carAoccupe un sous-ensemble à lui seul.
Le terme k*countP(n-1, k)
vient donc du cas oùAest pas dans un ensemble par lui-même. Nous calculons donc le nombre de façons de partitionner toutes les autres valeurs (N-1) en K sous-ensembles et nous les multiplions par K car il existe K sous-ensembles possibles auxquels nous pourrions ajouterA.
Par exemple, considérons l'ensemble [A,B,C,D]
, avec K=2
.
Le premier cas, countP(n-1, k-1)
, décrit la situation suivante:
{A, BCD}
Le deuxième cas, k*countP(n-1, k)
, décrit les cas suivants:
2*({BC,D}, {BD,C}, {B,CD})
Ou:
{ABC,D}, {ABD,C}, {AB,CD}, {BC,AD}, {BD,AC}, {B,ACD}
Comment pouvons-nous obtenir countP(n,k)
? En supposant que nous ayons divisé l'élément n-1
précédent en un certain nombre de partitions, nous avons maintenant le n-ième élément et nous essayons de créer une partition k
.
nous avons deux options pour cela:
non plus
n-1
précédents en partitions k
(nous avons countP(n-1, k)
façons de le faire) et nous plaçons ce nième élément dans l'une de ces partitions (nous avons k
choix). Nous avons donc k*countP(n-1, k)
.ou:
n-1
précédents en une partition k-1
(nous avons countP(n-1, k-1);
façons de le faire), et nous faisons du n-ème élément une partition unique pour réaliser une partition k
(nous n'avons qu'un choix: le mettre séparément). Nous avons donc countP(n-1, k-1);
. Nous les résumons donc et obtenons le résultat.
Sur la base de This , une partition d'un ensemble est un regroupement des éléments de l'ensemble en sous-ensembles non vides, de manière à ce que chaque élément soit inclus dans un et un seul des sous-ensembles. Ainsi, le nombre total de partitions d'un ensemble de n éléments est le numéro de Bell qui est calculé comme suit: formule du nombre de Bell Donc, si vous voulez convertir le formule à une fonction récursive ce sera comme: k * nombreP (n-1, k) + nombreP (n-1, k-1);