Contexte
Cette image illustre le problème :
Je peux contrôler le cercle rouge. Les cibles sont les triangles bleus. Les flèches noires indiquent la direction que les cibles vont suivre.
Je veux collecter toutes les cibles en un minimum de mouvements.
À chaque tour, je dois faire 1 pas vers la gauche, la droite, vers le haut ou vers le bas.
À chaque tour, les cibles feront également 1 pas selon les directions indiquées sur le tableau.
Démo
J'ai mis en place une démo jouable du problème ici sur Google appengine.
Je serais très intéressé si quelqu'un peut battre le score cible, car cela montrerait que mon algorithme actuel est sous-optimal. (Un message de félicitations devrait s'afficher si vous y parvenez!)
Problème
Mon algorithme actuel a une très mauvaise mise à l'échelle avec le nombre de cibles. Le temps augmente exponentiellement et pour 16 poissons, c'est déjà plusieurs secondes.
J'aimerais calculer la réponse pour des tailles de tableau de 32*32 et avec 100 cibles mobiles.
Question
Quel est un algorithme efficace (idéalement en Javascript) pour calculer le nombre minimal de mouvements pour collecter toutes les cibles?
Ce que j'ai essayé
Mon approche actuelle est basée sur la mémorisation mais elle est très lente et je ne sais pas si elle générera toujours la meilleure solution.
Je résous le sous-problème de "quel est le nombre minimal de mouvements pour collecter un ensemble donné de cibles et arriver à une cible particulière?".
Le sous-problème est résolu de manière récursive en examinant chaque choix pour la cible précédente à avoir visitée. Je suppose qu'il est toujours optimal de collecter le précédent sous-ensemble de cibles le plus rapidement possible puis de vous déplacer de la position où vous vous êtes arrêté à la cible actuelle le plus rapidement possible (bien que je ne sache pas si c'est une hypothèse valide).
Cela entraîne le calcul de n*2^n états, ce qui croît très rapidement.
Le code actuel est affiché ci-dessous :
var DX=[1,0,-1,0];
var DY=[0,1,0,-1];
// Retourne l'emplacement du poisson donné au temps t
function getPt(fish,t) {
var i;
var x=pts[fish][0];
var y=pts[fish][1];
for(i=0;i
`
Ce que j'ai considéré
Quelques options auxquelles j'ai réfléchi sont :
-
Mise en cache des résultats intermédiaires. Le calcul de distance répète beaucoup de simulations et les résultats intermédiaires pourraient être mis en cache.
Cependant, je ne pense pas que cela empêcherait l'obtention d'une complexité exponentielle. -
Un algorithme de recherche A* bien qu'il ne soit pas clair pour moi quelle heuristique admissible serait appropriée et à quel point cela serait efficace en pratique.
-
Enquêter sur de bons algorithmes pour le problème du voyageur de commerce et voir s'ils s'appliquent à ce problème.
-
Essayer de prouver que le problème est NP-difficile et donc déraisonnable de chercher une réponse optimale pour lui.
`