Le problème que tu décris est un problème d’optimisation non-linéaire. Il en existe un certain nombre de problèmes similaire qui sont NP-difficiles (en gros, ils n’ont pas de solution optimale qui se finissent en temps polynomial), donc le tiens est probablement aussi NP-difficile. Ça veux dire que à moins que le problème soit vraiment petit, tu n’as aucune chance de trouver un algorithme qui se fini en un temps raisonnable et qui est garanti de trouver une solution optimale.
Comme l’a dit @adri1, avec 89 objets et n compris entre 1 et 6, c’est assez petit pour tester toutes les solutions de manière exhaustive. L’estimation de moins d’une heure est assez pessimiste et je pencherais plus sur moins d’une minute avec un programme bien écrit et probablement de l’ordre de la seconde sur un bon ordinateur si tu parallélises la recherche (ce qui peut se faire de manière triviale).
Si n ou le nombre d’objet devient trop grand pour faire une recherche exhaustive, tu peut te tourner vers des algos heuristiques. D’expérience, la suggestion de @Karnaj de construire la solution de manière gloutonne ne va pas te donner un très bon résultat. Parmi la collection d’algos heuristiques, je une préférence pour utiliser un des trucs similaire au recuis simulé. Dans ton cas, tu peux simplement prendre au hasard n objets et ensuite améliorer itérativement cette solution. À chaque itération, tu choisis k éléments à remplacer, tu cherches de manière exhaustive les k nouveaux éléments qui te donnent le meilleur score. En pseudo-code, ça donne ça:
objets = liste d'objets possible
choisis = liste de n objets choisis aléatoirement parmi objets
score = score de choisis
boucle
à_remplacer = liste de k objets choisis aléatoirement parmi choisis
objets_stable = choisis - à_remplacer
meilleur_score = score
meilleur_k = à_remplacer
pour toutes les listes l de k objets parmi (objets - objets_stable)
nouveau_score = score de (objets_stable + l)
si nouveau_score > meilleur_score
meilleur_score = nouveau_score
meilleur_k = l
choisis = objets_stable + meilleur_k
score = score de choisis
afficher choisis et score
Pour que ça marche bien, il faut choisir le plus grand k qui permet à la boucle principale de s’exécuter rapidement (disons quelques dizaines/centaines de fois par secondes). Tu peux arrêter la boucle principale une fois que tu es satisfait du score obtenu.
Il reste un dernier détail important: vu qu’il est possible de diminuer ton score en ajoutant un nouvel objet, il y a de gros risques de tomber sur un optimum local qui est assez mauvais en comparaison de l’optimum global. Si tu relances l’algo décris précédemment (en t’assurant que le chois de la solution initiale est bien aléatoire) plusieurs fois, ça permet d’explorer à chaque fois des zones différentes de l’espace des solutions et donc te donne plus de chances de trouver l’optimum global (ou un bon optimum local). En allant plus loin, tu pourrais même biaiser la choix de la solution initiale pour diminuer les chances de choisir de nouveau des objets qui font parti de ta meilleur solution jusque là.