Antecedentes
Esta imagen ilustra el problema:
Puedo controlar el círculo rojo. Los objetivos son los triángulos azules. Las flechas negras indican la dirección en la que se moverán los objetivos.
Quiero recopilar todos los objetivos en el número mínimo de pasos.
Cada turno debo moverme 1 paso hacia la izquierda / derecha / arriba o abajo.
Cada turno, los objetivos también se moverán 1 paso de acuerdo con las instrucciones que se muestran en el tablero.
Manifestación
He puesto una demostración reproducible del problema aquí en Google appengine .
Me interesaría mucho si alguien puede superar la puntuación objetivo, ya que esto mostraría que mi algoritmo actual no es óptimo. (¡Debería imprimirse un mensaje de felicitación si logra esto!)
Problema
Mi algoritmo actual escala realmente mal con el número de objetivos. El tiempo aumenta exponencialmente y para 16 peces ya son varios segundos.
Me gustaría calcular la respuesta para tamaños de placa de 32 * 32 y con 100 objetivos móviles.
Pregunta
¿Cuál es un algoritmo eficiente (idealmente en Javascript) para calcular el número mínimo de pasos para recopilar todos los objetivos?
Lo que he probado
Mi enfoque actual se basa en la memorización, pero es muy lento y no sé si siempre generará la mejor solución.
Resuelvo el subproblema de "¿cuál es el número mínimo de pasos para recopilar un conjunto dado de objetivos y terminar en un objetivo en particular?".
El subproblema se resuelve de forma recursiva examinando cada opción para el objetivo anterior que ha visitado. Supongo que siempre es óptimo recopilar el subconjunto anterior de objetivos lo más rápido posible y luego pasar de la posición en la que terminó al objetivo actual lo más rápido posible (aunque no sé si esta es una suposición válida).
Esto da como resultado que se computen n * 2 ^ n estados que crecen muy rápidamente.
El código actual se muestra a continuación:
var DX=[1,0,-1,0];
var DY=[0,1,0,-1];
// Return the location of the given fish at time t
function getPt(fish,t) {
var i;
var x=pts[fish][0];
var y=pts[fish][1];
for(i=0;i<t;i++) {
var b=board[x][y];
x+=DX[b];
y+=DY[b];
}
return [x,y];
}
// Return the number of steps to track down the given fish
// Work by iterating and selecting first time when Manhattan distance matches time
function fastest_route(peng,dest) {
var myx=peng[0];
var myy=peng[1];
var x=dest[0];
var y=dest[1];
var t=0;
while ((Math.abs(x-myx)+Math.abs(y-myy))!=t) {
var b=board[x][y];
x+=DX[b];
y+=DY[b];
t+=1;
}
return t;
}
// Try to compute the shortest path to reach each fish and a certain subset of the others
// key is current fish followed by N bits of bitmask
// value is shortest time
function computeTarget(start_x,start_y) {
cache={};
// Compute the shortest steps to have visited all fish in bitmask
// and with the last visit being to the fish with index equal to last
function go(bitmask,last) {
var i;
var best=100000000;
var key=(last<<num_fish)+bitmask;
if (key in cache) {
return cache[key];
}
// Consider all previous positions
bitmask -= 1<<last;
if (bitmask==0) {
best = fastest_route([start_x,start_y],pts[last]);
} else {
for(i=0;i<pts.length;i++) {
var bit = 1<<i;
if (bitmask&bit) {
var s = go(bitmask,i); // least cost if our previous fish was i
s+=fastest_route(getPt(i,s),getPt(last,s));
if (s<best) best=s;
}
}
}
cache[key]=best;
return best;
}
var t = 100000000;
for(var i=0;i<pts.length;i++) {
t = Math.min(t,go((1<<pts.length)-1,i));
}
return t;
}
Lo que he considerado
Algunas opciones sobre las que me he preguntado son:
Almacenamiento en caché de resultados intermedios. El cálculo de la distancia repite mucha simulación y los resultados intermedios pueden almacenarse en caché.
Sin embargo, no creo que esto impida que tenga una complejidad exponencial.Un algoritmo de búsqueda A *, aunque no me queda claro cuál sería una heurística admisible apropiada y qué tan efectivo sería en la práctica.
Investigar buenos algoritmos para el problema del viajante y ver si se aplican a este problema.
Tratar de demostrar que el problema es NP-difícil y, por lo tanto, no es razonable buscar una respuesta óptima.