... bir NPC probleminden bir düşüş oluşturmak için bazı desenler aradım, ancak “çatal” ile “akış” ı temsil etmenin bir yolunu bulamadım ...
Yani (bazı işten sonra) bu polinom bir algoritma ...
ALGORITMASı
Başlangıç listesi, ardışık " delikler " dizisi olarak görüntülenebilir . Her başlangıç çifti için , " element " delik numarasına . Her çift konumundan konumuna yönlendirilmiş bir kenar olarak . Bir hareket , pozisyonunda elemanının ve onu hedef pozisyonuna hareket ettirmekten (hedef deliği mandal haline gelir ). Kenarı siliyoruz ve en yakın ulaşılabilir iki unsurdan birinden başlayacak olan sonraki hareketi seçmeye devam ediyoruz.( a j , b j ) b j a j a j b j b j a j b j b k b j b j b k NN∗2(aj,bj)bjajajbjbjajbjbk , (sadece ve arasındaki deliklere izin verilir). ardışık hamle dizisini bulmalıyız .bjbjbkN
Bir hamle, pozisyon bir PEG saptamak ve dizi iki bölüm içinde ayrılmıştır olduğunu (sol) ve (sağ) ve gitmek için tek yol için (veya için ) bir kenar kullanıyor mandalın karşısındaki zıplama. setbjLRLRRL
- edgesLR = soldan sağa olan kenarların sayısı (son kenarı )
- edgesRL = sağdan sola doğru kenar sayısı (son kenarı sayma)
- flow =edgesLR−edgesRL
Durumlar:
A) eğer sonra iki bölümden birine ulaşılamaz hale gelecektir.|flow|>1
Şimdi bu , yaniend>bjend∈R
B) eğer ise soldan sağa ekstra bir kenar varsa, sola gitmelisin ( nin en yakın elemanını seç ), aksi takdirde aslaflow=1Lend
C) eğer ise sağdan sola doğru fazladan bir kenar vardır ve seçtiğiniz düğüm hiçbir zaman ,flow=−1end
Eğer D) doğru gitmek gerekir (en yakın eleman almak aksi takdirde ulaşmak neve olacak)flow=0Rend
Eğer ( ), B, C, D ters çevrilir.end<bjend∈L
NOT: sola veya sağa hareket ederken, mandal olarak düşünmelisiniz . Örneğin, doğru gitmek gerekir, ama en yakın eleman eğer olduğunu sonra hareket imkansızdır (ve başka bir çift yürütülmesi gerektiğini )endRend(start,end)
Her harekette aynı rezonansı uygulayın.
KOMPLEKSLİĞİ
Her deliğin üzerindeki akışlar O (N) cinsinden önceden hesaplanabilir ve her taramada tekrar kullanılabilir.
Döngüler:
for start = 1 to N
for end = 1 to N
for move = 1 to N
make a move (fix a peg and update flows)
check if another move can be done using flow
Hesaplama sırasında hiçbir seçim yapılmadığından algoritmanın karmaşıklığıO(N3)
KOD
Bu, algoritmanın çalışan bir Java uygulamasıdır:
public class StrangeSort {
static int PEG = 0xffffff, HOLE = 0x0;
static int M = 0, N = 0, choices = 0, aux = 0, end;
static int problem[][], moves[], edgeflow[], field[];
boolean is_hole(int x) { return x == HOLE; }
boolean is_peg(int x) { return x == PEG; }
boolean is_ele(int x) { return ! is_peg(x) && ! is_hole(x); };
int []cp(int src[]) { // copy an array
int res[] = new int[src.length];
System.arraycopy(src, 0, res, 0, res.length);
return res;
}
/* find the first element on the left (dir=-1) right (dir=1) */
int find(int pos, int dir, int nm) {
pos += dir;
while (pos >= 1 && pos <= M ) {
int x = field[pos];
if ( is_peg(x) || (pos == end && nm < N-1) ) return 0;
if ( is_ele(x) ) return pos;
pos += dir;
}
return 0;
}
void build_edges() {
edgeflow = new int[M+1];
for (int i = 1; i<=M; i++) {
int start = i;
int b = field[start];
if (! is_ele(b)) continue;
if (i == end) continue;
int dir = (b > start)? 1 : -1;
start += dir;
while (start != b) { edgeflow[start] += dir; start += dir; }
}
}
boolean rec_solve(int start, int nm) {
boolean f;
int j;
int b = field[start];
moves[nm++] = b;
if (nm == N) return true;
//System.out.println("Processing: " + start + "->" + field[start]);
field[start] = HOLE;
field[b] = PEG;
int dir = (b > start)? 1 : -1;
int i = start + dir;
while (i != b) { edgeflow[i] -= dir; i += dir; } // clear edge
int flow = edgeflow[b];
if (Math.abs(flow) > 2) return false;
if (end > b) {
switch (flow) {
case 1 :
j = find(b,-1,nm);
if (j <= 0) return false;
return rec_solve(j,nm);
case -1 :
return false;
case 0 :
j = find(b,1,nm);
if (j <= 0) return false;
return rec_solve(j,nm);
}
} else {
switch (flow) {
case -1 :
j = find(b,1,nm);
if (j <= 0) return false;
return rec_solve(j,nm);
case 1 :
return false;
case 0 :
j = find(b,-1,nm);
if (j <= 0) return false;
return rec_solve(j,nm);
}
}
return false;
}
boolean solve(int demo[][]) {
N = demo.length;
for (int i = 0; i < N; i++)
M = Math.max(M, Math.max(demo[i][0], demo[i][1]));
moves = new int[N];
edgeflow = new int[M+1];
field = new int[M+1];
problem = demo;
for (int i = 0; i < problem.length; i++) {
int a = problem[i][0];
int b = problem[i][1];
if ( a < 1 || b < 1 || a > M || b > M || ! is_hole(field[a]) || ! is_hole(field[b])) {
System.out.println("Bad input pair (" + a + "," + b + ")");
return false;
}
field[a] = b;
}
for (int i = 1; i <= M; i++) {
end = i;
build_edges();
if (!is_ele(field[i])) continue;
for (int j = 1; j <= M; j++) {
if (!is_ele(field[j])) continue;
if (i==j) continue;
int tmp_edgeflow[] = cp(edgeflow);
int tmp_field[] = cp(field);
choices = 0;
//System.out.println("START: " + j + " " + " END: " + i);
if (rec_solve(j, 0)) {
return true;
}
edgeflow = tmp_edgeflow;
field = tmp_field;
}
}
return false;
}
void init(int demo[][]) {
}
public static void main(String args[]) {
/**** THE INPUT ********/
int demo[][] = {{4,2},{5,7},{6,3},{10,12},{11,1},{13,8},{14,9}};
/***********************/
String r = "";
StrangeSort sorter = new StrangeSort();
if (sorter.solve(demo)) {
for (int i = 0; i < N; i++) { // print it in clear text
int b = moves[i];
for (int j = 0; j < demo.length; j++)
if (demo[j][1] == b)
r += ((i>0)? " -> " : "") + "(" + demo[j][0] + "," + demo[j][1] + ")";
}
r = "SOLUTION: "+r;
}
else
r = "NO SOLUTIONS";
System.out.println(r);
}
}