public class Pieces {
// affiche une solution...
public static void affiche(int []essai,
int []valeursFaciales) {
for (int i=0; i<essai.length; i++) {
if (essai[i]!=0)
System.out.print(essai[i]+"x"+valeursFaciales[i]+" + ");
}
System.out.println();
}
// une solution est-elle correcte ? ie: la somme correspondante est-elle égale à
// la somme cherchée ?
public static boolean correct(int []essai,
int []valeursFaciales,
int sommeAAtteindre) {
int sommeEssai = 0;
for (int i=0; i<essai.length; i++) {
sommeEssai += valeursFaciales[i]*essai[i];
}
return sommeEssai==sommeAAtteindre;
}
// compteurs divers
public static int compteur;
public static int solutions;
// exploration exhaustive, ie qui teste toutes les possibilités y compris les
// plus absurdes
public static void explore(int type,int []valeurs,int []essai,int somme,
int []nombre) {
compteur++; // un essai de plus
if (type==valeurs.length) { // si on a fini de fabriquer une solution potentielle
if (correct(essai,valeurs,somme)) { // on teste si c'est une solution correcte
solutions++; // une solution correcte de plus
affiche(essai,valeurs); // on l'affiche
}
return; // dans tous les cas (bonne ou pas bonne) on revient à une évenutelle possibilité suivante
}
// On essaie toutes les possibilités pour une valeur faciale donnée, donc
// toutes les combinaisons qui font apparaître de 0 au nombre d'exemplaires
// possible pour cette pièce.
for (int choix=0; choix<=nombre[type]; choix++) {
essai[type] = choix; // on effectue un choix
explore(type+1,valeurs,essai,somme,nombre); // on essaie de complémenter la solution partielle
}
}
// le même algorithme avec rebroussement (backtracking)
// il y a un argumehnt de plus qui correspond à la somme déjà accumulée au fur
// et à mesure de la construction de la solution...
public static void explore2(int type,int []valeurs,int []essai,int somme,
int []nombre,int accumulation) {
compteur++; // un test de plus
if (accumulation>somme) return; // on coupe l'exploration à ce niveau car on a déjà dépassé notre but, inutile de rajouter des pièces
if (type==valeurs.length) { // si on est arrivé à construire une solution complète
// if (correct(essai,valeurs,somme)) {
if (accumulation==somme) { // et que la somme accumulée correspond au but fixé
solutions++; // une solution de plus
affiche(essai,valeurs); // que l'on affiche
}
return; // dans tous les cas, on revient à un choix précédent pour passer à un éventuel choix suivant
}
// on essaie toutes les possibilités pour la valeur faciale courante
for (int choix=0; choix<=nombre[type]; choix++) {
essai[type] = choix; // on enregistre le choix
explore2(type+1,valeurs,essai,somme,nombre,accumulation+choix*valeurs[type]); // on accumule la somme correspondant au choix que l'on vient de faire
}
}
public static void main(String []a) {
// valeurs faciales
int []valeurs = { 1, 2, 5, 7, 13 };
// exemplaires disponibles
int []nombre = { 7, 2, 0, 1, 20 };
// essai (au début ne contient rien)
int []essai = new int[nombre.length];
// somme à atteindre (faire joujou avec la valeur)
int somme = 278;
System.out.println("Exploration complete");
compteur = 0; solutions = 0;
explore(0,valeurs,essai,somme,nombre);
System.out.println("J'ai exploré "+compteur+" solutions et j'en ai trouvé "+solutions);
System.out.println("avec rebroussement");
compteur = 0; solutions = 0;
explore2(0,valeurs,essai,somme,nombre,0);
System.out.println("J'ai exploré "+compteur+" solutions et j'en ai trouvé "+solutions);
}
}