Arka fon
Bu resim sorunu göstermektedir:
Kırmızı daireyi kontrol edebilirim. Hedefler mavi üçgenler. Siyah oklar, hedeflerin hareket edeceği yönü gösterir.
Tüm hedefleri minimum adım sayısında toplamak istiyorum.
Her dönüşte 1 adım sola / sağa / yukarı veya aşağı hareket etmeliyim.
Her dönüşte hedefler ayrıca tahtada gösterilen talimatlara göre 1 adım hareket edecektir.
Demo
Sorunun oynanabilir bir demosunu burada Google uygulama motoruna koydum .
Mevcut algoritmamın yetersiz olduğunu göstereceğinden, herhangi biri hedef puanı geçebilirse çok ilgilenirim. (Bunu yönetirseniz bir tebrik mesajı yazdırılmalıdır!)
Sorun
Mevcut algoritmam hedeflerin sayısına göre gerçekten kötü bir şekilde ölçekleniyor. Zaman katlanarak artar ve 16 balık için zaten birkaç saniyedir.
32 * 32 tahta boyutları ve 100 hareketli hedef için cevabı hesaplamak istiyorum.
Soru
Tüm hedefleri toplamak için minimum adım sayısını hesaplamak için etkili bir algoritma (ideal olarak Javascript'te) nedir?
Ne denedim
Şu anki yaklaşımım ezbere dayanıyor ama çok yavaş ve her zaman en iyi çözümü üretip üretmeyeceğini bilmiyorum.
"Belirli bir hedef kümesini toplamak ve belirli bir hedefe ulaşmak için gereken minimum adım sayısı nedir?" Alt problemini çözüyorum.
Alt problem, önceki hedefin ziyaret ettiği her bir seçim incelenerek özyinelemeli olarak çözülür. Önceki hedef alt kümesini olabildiğince çabuk toplayıp, sonlandırdığınız konumdan mevcut hedefe mümkün olan en kısa sürede geçmenin her zaman en uygun olduğunu varsayıyorum (bunun geçerli bir varsayım olup olmadığını bilmeme rağmen).
Bu, çok hızlı büyüyen n * 2 ^ n durumlarının hesaplanmasına neden olur.
Mevcut kod aşağıda gösterilmiştir:
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;
}
Ne düşündüm
Merak ettiğim bazı seçenekler:
Ara sonuçların önbelleğe alınması. Mesafe hesaplaması birçok simülasyonu tekrar eder ve ara sonuçlar önbelleğe alınabilir.
Ancak bunun üstel karmaşıklığa sahip olmasını engelleyeceğini sanmıyorum.Bir A * arama algoritması, uygun bir kabul edilebilir buluşsal yöntemin ne olacağı ve bunun pratikte ne kadar etkili olacağı benim için açık olmasa da.
Gezgin satıcı problemi için iyi algoritmaları araştırmak ve bu probleme uygulayıp uygulamadıklarına bakmak.
Sorunun NP-zor olduğunu ve dolayısıyla bunun için en uygun cevabı aramak mantıksız olduğunu kanıtlamaya çalışmak.