Bonsoir,
J’essaie de résoudre un problème algorithmique proprement mais j’ai un peu de mal. Voici le problème :
- On vous donne un entier $n$
- On vous donne $n$ entiers non nécessairement positif
- Afficher toutes les sommes qu’il est possible d’effectuer avec ces entiers.
Par exemple : Si l’utilisateur entre l’entier $n = 3$, et les trois entiers $1, 2, 3$ alors le programme devra afficher $1, 2, 3, 4, 5$, car $1+2 = 3$, $ 2+3 = 5$…
Bon, tout d’abord je me dis qu’une résolution fera sûrement intervenir un algorithme récursif car je vois difficilement comment un algorithme itératif peut marcher dès lors que $n$ est inconnu avant compilation.
Voilà l’idée de l’algorithme que j’ai implémenté :
On prend deux tableaux, l’un va contenir les éléments entrés par l’utilisateur l’autre l’ensemble des sommes possibles. Je fais une boucle for sur le premier tableau et je pop un élément de ce tableau et j’appelle la fonction.
Bon ce n’est pas très clair, donc voilà son implémentation en C++ :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #include<iostream> #include<vector> #include<list> #include<algorithm> #include <numeric> void calcSum (std::vector<int> actual, std::list<int> &allSum) { std::vector<int>copy; if (actual.size() == 0 ){return;} allSum.push_back (std::accumulate(begin(actual), end(actual), 0)); for (size_t i = 0; i < actual.size(); ++i) { copy = actual; copy.erase(copy.begin()+i); calcSum(copy, allSum); } } int main() { std::list<int>allSum; std::vector<int>actual; unsigned int n {0}; std::cin >> n; int inter {0}; for (int i = 0; i < n; ++i) { std::cin >> inter; actual.push_back(inter); } calcSum(actual, allSum); std::list<int>::const_iterator lit (allSum.begin()), lend(allSum.end()); for(;lit!=lend;++lit) std::cout << *lit << ' '; return 0; } |
Ce code marche parfaitement et m’affiche bien toutes les sommes possibles, néanmoins le problème est qu’il calcule plusieurs fois la même somme. J’ai quand même essayer de faire attention aux structures de données en prenant une liste pour toutes les sommes car l’ajout d’un élément à une liste est en $\mathcal O (1)$ alors que pour un vector il est en $\mathcal O(n)$. Malheureusement cela est négligeable car mon algorithme si je ne me trompe pas tourne en $\mathcal O(n^n)$, ce qui est plutôt énorme.
De plus par rapport à l’énoncé de l’exercice puisque :
alors il est sûrement possible d’implémenter une algorithme en $\mathcal O (2^n)$ et je suis loin du compte.
C’est pourquoi si des personnes ont des idées d’algo plus opti que celui que je propose ou une autre manière de voir les choses, ou encore des suggestions par rapport aux structures de données utilisées n’hésitez pas :p.
Merci d’avance.
Bonne soirée.