... NPCの問題を軽減するためにいくつかのパターンを検索しましたが、「フォーク」で「フロー」を表す方法が見つかりませんでした...
(ある程度の作業の後)これは多項式アルゴリズムです...
アルゴリズム
開始リストは、連続した「穴」の配列として表示できます。初期ペアごとに、「要素」を穴番号ます。各ペアは、位置から有向エッジと見なすことができる位置に。この動きは、素子ピッキングからなる位置におよびその先の位置に移動(先孔は不動となるPEG)。エッジを削除し、2つの最も近い到達可能な要素のいずれかから開始する次の移動の選択に進みます(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位置からの(と間の穴のみが許可されます)。連続した動きのシーケンスを見つけなければなりません。bjbjbkN
移動するとき、位置ペグを修正し、配列は2つのパーティション(左)と(右)に分割され、から(またはから)に進む唯一の方法はエッジを使用することですペグを飛び越えます。セット L R L R R LbjLRLRRL
- edgesLR =左から右へのエッジの数(最終エッジをカウントしない)
- edgesRL =右から左へのエッジの数(最終エッジはカウントしません)
- e d g e s L R − e d g e s R Lflow =edgesLR−edgesRL
事例:
A)if場合、2つのパーティションのいずれかが到達不能になり、停止します|flow|>1
ここで、、つまりと仮定します。 E N D ∈ Rend>bjend∈R
B)の場合その後、左から右に余分なエッジは、あなたが最も近い要素選ぶ(左に行く必要がありますありそれ以外の場合は、あなたが到達することはありません、)L e n dflow=1Lend
C)場合、右から左に余分なエッジがあり、選択したノードはに到達しません。stope n dflow=−1end
D)場合、右に移動する(の最も近い要素を選択する)必要があります。そうでない場合は、到達する必要がありますR e n dflow=0Rend
場合()、B、C、Dが反転されます。 E N D ∈ Lend<bjend∈L
注:左または右に移動するときは、をペグと見なす必要があります。たとえば、右に行かなければならないが、の最も近い要素が場合、移動は不可能です(そして、別のペア進む必要があります)R e n d (s t a r t 、e n d )endRend(start,end)
すべての動きで同じ共鳴を適用します。
複雑
各穴の上の流れはO(N)で事前に計算され、スキャンごとに再利用できます。
ループは次のとおりです。
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
計算中に選択は行われないため、アルゴリズムの複雑さはO(N3)
コード
これは、アルゴリズムの動作するJava実装です。
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);
}
}