Une façon directe est une procédure récursive qui effectue les opérations suivantes à chaque appel. L'entrée de la procédure est une liste de paires qui ont déjà été choisies et une liste de toutes les paires.
- Calculez le plus petit nombre non déjà couvert par la liste d'entrée. Pour la première invocation, ce sera bien sûr 0, car aucune paire n'a été choisie.
- Si tous les numéros sont couverts, vous avez une combinaison correcte, imprimez-la et retournez à l'étape précédente. Sinon, le plus petit nombre qui est découvert est la cible que nous viserons.
- Cherchez parmi les paires à la recherche d'un moyen de couvrir le nombre cible. S'il n'y en a pas, revenez simplement au niveau de récursivité précédent.
- S'il existe un moyen de couvrir le nombre cible, choisissez la première méthode et appelez à nouveau de manière récursive la procédure entière, la paire venant d'être ajoutée s'ajoutant à la liste des paires choisies.
- Lorsque cela revient, cherchez la prochaine façon de couvrir le nombre cible avec une paire, sans chevaucher une paire précédemment choisie. Si vous en trouvez un, choisissez-le et appelez à nouveau de manière récursive la procédure suivante.
- Continuez les étapes 4 et 5 jusqu'à ce qu'il n'y ait plus de moyens de couvrir le nombre cible. Parcourez la liste complète des paires. Lorsqu'il n'y a plus de choix corrects, revenez au niveau précédent de la récursivité.
La façon de visualiser cet algorithme est avec un arbre dont les chemins sont des séquences de paires qui ne se chevauchent pas. Le premier niveau de l'arbre contient toutes les paires qui contiennent 0. Pour l'exemple ci-dessus, l'arbre est
Racine
|
----------------
| | |
(0,1) (0,2) (0,3)
| | |
(2,3) (1,3) (1,2)
Dans cet exemple, tous les chemins dans l'arborescence donnent des collections correctes, mais par exemple, si nous omettons la paire (1,2), le chemin le plus à droite n'aurait qu'un seul nœud et correspondrait à l'échec de la recherche à l'étape 3.
Des algorithmes de recherche de ce type peuvent être développés pour de nombreux problèmes similaires d'énumération de tous les objets d'un type particulier.
Il a été suggéré que peut-être le PO signifiait que toutes les paires sont dans l'entrée, pas seulement un ensemble d'entre elles comme le dit la question. Dans ce cas, l'algorithme est beaucoup plus facile car il n'est plus nécessaire de vérifier quelles paires sont autorisées. Il n'est même pas nécessaire de générer l'ensemble de toutes les paires; le pseudocode suivant fera ce que l'OP a demandé. Ici, est le numéro d'entrée, "liste" commence comme une liste vide et "couvert" est un tableau de longueur n initialisé à 0. Il pourrait être rendu un peu plus efficace mais ce n'est pas mon objectif immédiat.nn
sub cover {
i = 0;
while ( (i < n) && (covered[i] == 1 )) {
i++;
}
if ( i == n ) { print list; return;}
covered[i] = 1;
for ( j = 0; j < n; j++ ) {
if ( covered[j] == 0 ) {
covered[j] = 1;
push list, [i,j];
cover();
pop list;
covered[j] = 0;
}
}
covered[i] = 0;
}