重排九宫是一个古老的单人智力游戏。据说重排九宫起源于我国古时由三国演义故事“关羽义释曹操”而设计的智力玩具“华容道”,后来流传到欧洲,将人物变成数字。原始 的重排九宫问题是这样的:将数字 1~8 按照任意次序排在 3×3 3 × 3 的方格阵列中,留下一个空 格。与空格相邻的数字,允许从上,下,左,右方向移动到空格中。游戏的最终目标是通过 合法移动,将数字 1~8 按行排好序。最长距离问题考察的是,从数字 1~8 在 3×3 3 × 3 的方格阵 列的初始排列 A 出发,找出与其相应的最长距离目标状态 B。换句话说,从 A 到 B 的最优移动序列的长度最长。
对于给定的 3×3 3 × 3 方格阵列中数字 1~8 初始排列,编程计算与初始排列相应的最长距离目标状态。
数据输入:
有 3 行,每行有 3 个数字表示该行方格中的数字, 0 表示空格。
package Chapter6FenZhiXianJieFa;
import java.util.Scanner;
public class ZuiChangJuLi {
private static class Node{
int code,dep,dir,parent;
}
private static final char[] op = {'U','D','L','R'};
private static final int Bitsint = 32;
private static final int Rowsz = 3;
private static final int Permsz = Rowsz*Rowsz;
private static Node[] buff;
private static int first,last,fact,masksz;
private static int[] bitset;
private static int[] sour = new int[Permsz];
private static int[] perm = new int[Permsz];
public static void main(String[] args){
Scanner input = new Scanner(System.in);
while (true){
init(input);
fifobb();
output();
}
}
private static void init(Scanner input){
fact = 1;
for(int i=0,n=0; iif(n == 0) sour[i]=Permsz-1;
else sour[i]=n-1;
fact *= i+1;
perm[i] = sour[i];
}
int icode = ptoi(sour);
masksz = (fact+Bitsint-1)/Bitsint;
bitset = new int[masksz];
for(int i=0; i0;
bitset[icode/Bitsint] |= 1<<(icode%Bitsint);
first=0; last=0;
buff = new Node[fact/2];
for(int i=0; i2; i++)
buff[i] = new Node();
buff[last].parent = -1;
buff[last].dep = 0;
buff[last++].code = icode;
}
private static int ptoi(int[] perm){
int[] pcpy = new int[Permsz];
int[] invp = new int[Permsz];
int n = 0;
for(int i=0; ifor(int i=Permsz-1; i>0; i--){
int p = invp[i];
pcpy[p] = pcpy[i];
pcpy[i] = i;
invp[pcpy[p]] = p;
invp[i] = i;
n *= i+1;
n += i-p;
}
return n;
}
private static void itop(int[] perm, int n){
perm[0] = 0;
for(int i=1; iint p = i-n%(i+1);
perm[i] = perm[p];
perm[p] = i;
n /= i+1;
}
}
private static void fifobb(){
while (first < fact/2){
int code = buff[first].code;
itop(perm,code);
int i;
for(i=0; perm[i]!=Permsz-1 && iint brow = i/Rowsz;
int bcol = i%Rowsz;
for(int d=0; d<4; d++) trymove(brow,bcol,i,d);
first++;
}
}
private static void trymove(int brow, int bcol, int i, int d){
switch (d){
case 0:
if(brow > 0){
swap(perm,i,i-Rowsz);
addperm(d);
swap(perm,i,i-Rowsz);
}
break;
case 1:
if(brow < Rowsz-1){
swap(perm,i,i+Rowsz);
addperm(d);
swap(perm,i,i+Rowsz);
}
break;
case 2:
if(bcol > 0){
swap(perm,i,i-1);
addperm(d);
swap(perm,i,i-1);
}
break;
case 3:
if(bcol < Rowsz-1){
swap(perm,i,i+1);
addperm(d);
swap(perm,i,i+1);
}
}
}
private static void swap(int[] perm, int i, int j){
int tmp = perm[i];
perm[i] = perm[j];
perm[j] = tmp;
}
private static void addperm(int dir){
int code = ptoi(perm);
int m = code/Bitsint;
int n = code%Bitsint;
if(((bitset[m]>>n)&1) > 0) return;
bitset[m] |= 1<1;
buff[last++].code = code;
}
private static void output(){
int best = 0;
int i;
int j = 0;
for(i=0; i2; i++)
if(buff[i].dep >= best){
best = buff[i].dep;
j = i;
}
for(i=0,j=0; i2; i++)
if(buff[i].dep == best)
j++;
System.out.println(best+" "+j);
for(i=0,j=0; i2; i++)
if(buff[i].dep == best){
itop(perm,buff[i].code);
outperm();
outmove(i);
System.out.println();
}
}
private static void outmove(int first){
if(buff[first].dep == 0) return;
outmove(buff[first].parent);
System.out.print(op[buff[first].dir]);
}
private static void outperm(){
for(int i=0; i1)%Permsz+" ");
if((i+1)%Rowsz == 0)
System.out.println();
}
}
}
2 6 4
1 3 7
0 5 8
31 2
8 7 1
0 3 5
4 6 2
UURDDLUURRDDLURDLLUURDLURRDDLLU
8 1 5
7 3 6
4 0 2
UURDDRULLURRDLLDRRULULDDRUULDDR
7 0 3
8 1 2
6 5 4
31 2
4 6 0
2 1 5
3 8 7
DDLUURRDDLULURRDDLULURRDDLLUURR
0 4 6
5 1 8
3 2 7
DDLURRULLDRRDLLURURDDLUURDDLLUU
0 8 6
5 4 7
2 3 1
31 2
1 3 2
0 4 8
6 7 5
DDRUULDDRRUULDRULLDDRULDRRUULLD
1 0 2
7 4 3
6 5 8
DDRUURDLLDRRULLURRDLDLUURDDLUUR
王晓东《计算机算法设计与分析》