康托展开 + 离线bfs(打表) ,菜的不说了,wa了一页( javaio真杀死我)
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main{
static int FAC[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880}; // 阶乘
static int cantor(int [] a, int n)
{
int x = 0;
for (int i = 0; i < n; ++i) {
int smaller = 0; // 在当前位之后小于其的个数
for (int j = i + 1; j < n; ++j) {
if (a[j] < a[i])
smaller++;
}
x += FAC[n - i - 1] * smaller; // 康托展开累加
}
return x+1; // 康托展开值
}
static String[] solution;
static int[] vis;
static int[] xx= {-1,1,0,0};
static int[] yy= {0,0,-1,1};
static class Node{
int[] a;
int pos;
}
static String [] ss = {"d","u","r","l"};
static void bfs() {
vis=new int [370000];
solution = new String[370000];
Queue<Node> q= new LinkedList<Node>();
Node node = new Node();
node.a = new int[] {1,2,3,4,5,6,7,8,0};
node.pos=8;
solution[cantor(node.a,9)]="";
q.add(node);
while(!q.isEmpty()) {
Node top = q.poll();
for(int i=0;i<4;i++) {
int x2 = top.pos/3 + xx[i];
int y2 = top.pos%3 + yy[i];
int newpos = x2*3+y2;
if(x2>-1 &&x2<3 && y2>-1 && y2<3) {
int[] a2 = new int [9];
a2 = Arrays.copyOf(top.a, top.a.length);
a2[top.pos] = a2[newpos]; //交换指定位置
a2[newpos] = 0;
Node newnode = new Node();//构建个节点
newnode.a = a2;
newnode.pos=newpos;
int kt1 = cantor(top.a,9); //旧状态和新状态的cantor值
int kt2 =cantor(a2 ,9);
if( vis[kt2]==0) {
vis[kt2] = 1 ;
solution[kt2]="";
solution[kt2]=solution[kt1]+ss[i];
q.add(newnode);
}
}
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
bfs();
while(sc.hasNext()) {
int[] aa = new int[9];
int con = 0;
while(con!=9) {
String c = sc.nextLine();
for(int i=0;i<c.length();i++) {
if(c.charAt(i)=='x') {
aa[con++]=0;
}else if(c.charAt(i)>='0' && c.charAt(i)<='8'){
aa[con++]=c.charAt(i)-'0';
}
}
}
int temp = cantor(aa,9);
if(vis[temp] ==1 ) {
String res = solution[temp];
System.out.println(new StringBuilder(res).reverse().toString());
}else
System.out.println("unsolvable");
}
}
}