<span style="font-family: Arial, Helvetica, sans-serif;">题意:省略</span>
解题思路:针对八数码问题,如果x往左或往右走,是不会改变逆序数大小的,且往上或往下走只有三种情况,讨论往下走,如果与x交换的数是ai,则要判断的是a(i-1),a(i-2)与ai的关系.
只会出现四种情况,a(i-1)>ai,a(i-2)>ai;逆序对数在原来的基础上+2
a(i-1)<ai,a(i-2)>ai;逆序对数在原来的基础上不变
a(i-1)>ai,a(i-2)<ai;逆序对数在原来的基础上不变
a(i-1)<ai,a(i-2)<ai;逆序对数在原来的基础上-2
针对上述四种情况,逆序数的初始值为0,则经过各种变换逆序数为偶数,则若一种状态逆序数为奇数,始不可能的。且在保存状态时利用康托展开:X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! (ai为某个数对应的逆序对数,达到状态压缩)。
这里要利用反向的思维,通过最终状态去bfs所有状态。
只会出现四种情况,a(i-1)>ai,a(i-2)>ai;逆序对数在原来的基础上+2
a(i-1)<ai,a(i-2)>ai;逆序对数在原来的基础上不变
a(i-1)>ai,a(i-2)<ai;逆序对数在原来的基础上不变
a(i-1)<ai,a(i-2)<ai;逆序对数在原来的基础上-2
针对上述四种情况,逆序数的初始值为0,则经过各种变换逆序数为偶数,则若一种状态逆序数为奇数,始不可能的。且在保存状态时利用康托展开:X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! (ai为某个数对应的逆序对数,达到状态压缩)。
这里要利用反向的思维,通过最终状态去bfs所有状态。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <queue>
using namespace std;
#define MAXN 50
#define MAZE 600000
typedef struct node{
char str[50];
int nx[9];
int num,hashnum,xind;
node();
node(char *ss,int nu,int hanu,int *nnx){
strcpy(str,ss);
num = nu;
hashnum = hanu;
for(int i=0;i<9;++i){
nx[i] = nnx[i];
}
}
void charstr(){
int tmp = 0;
int tmpc;
int tmpnum = num;
tmpc = 9;
int zflag = 0;
while(num){
zflag = num%10;
str[tmpc -1] = '0'+ zflag;
if(zflag==9)
tmp = tmpc - 1;
num/=10;
--tmpc;
}
num = tmpnum;
xind = tmp;
//return tmp;
}
};
queue<node>q;
int path[MAZE];
int nx[9];
int pa[MAZE],ans[MAZE];
bool vis[MAZE];
char nows[MAXN];
int cnt;
int p[]={1,1,2,6,24,120,720,5040,40320};
int pw[] = {100000000,10000000,1000000,100000,10000,1000,100,10,1};
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
int goal;
void prepro(){
cnt = 0;
int len = (int)strlen(nows);
for(int i=0;i<len;++i){
if(nows[i]==32)continue;
if(nows[i]=='x')nows[i] = '9';
nows[cnt++] = nows[i];
}
nows[cnt] = 0;
}
void init(){
memset(vis,false,sizeof(vis));
memset(pa,-1,sizeof(pa));
}
int charhash(char *str){
//就保证系数ai》=0&&ai<=(8 - i)
int ans = 0,tmpc;
int st = 0;
for(int i=0;i<cnt;++i){
//if(nows[i]=='x')continue;
tmpc = 0;
for(int j = i+1;j<cnt;++j){
// if(nows[j]=='x')continue;
if(str[i]>str[j])tmpc++;
}
nx[i] = tmpc;
ans+=tmpc*p[8-i];
//st++;
}
return ans;
}
int getnx(){
int ans = 0;
for(int i=0;i<cnt;++i){
//if(nows[i]=='x')continue;
if(nows[i]=='9')continue;
for(int j=i+1;j<cnt;++j){
// if(nows[j]=='x')continue;
if(nows[i]>nows[j])
ans++;
}
}
return ans;
}
int getnumber(){
int ans = 123456789;
return ans;
}
//右 左 下 上
int gethash(char *str,int num,int dir,int xind,int nxind,node &no){
int tmpcc;
if(dir==0){
num = num-p[8-xind]*no.nx[xind] - p[8-nxind]*no.nx[nxind];
tmpcc = no.nx[nxind];
no.nx[nxind]=no.nx[xind] - 1;
no.nx[xind] = tmpcc;
num+=p[8-xind]*no.nx[xind] + p[8-nxind]*no.nx[nxind];
}
if(dir==1){
num = num-p[8-xind]*no.nx[xind] - p[8-nxind]*no.nx[nxind];
tmpcc = no.nx[nxind];
no.nx[nxind]=no.nx[xind] + 1;
no.nx[xind] = tmpcc;
num+=p[8-xind]*no.nx[xind] + p[8-nxind]*no.nx[nxind];
}
if(dir==2){
int ind1,ind2;
ind1 = xind+1;
ind2 = xind+2;
int cc = 0;
if(str[nxind]>str[ind1])cc++;
if(str[nxind]>str[ind2])cc++;
num = num-p[8-xind]*no.nx[xind] - p[8-nxind]*no.nx[nxind];
tmpcc = no.nx[nxind];
no.nx[nxind]=no.nx[xind] - 3;
no.nx[xind] = tmpcc+cc;
num+=p[8-xind]*no.nx[xind] + p[8-nxind]*no.nx[nxind];
if(str[nxind]<str[ind1]){
num-=p[8-ind1];
no.nx[ind1]--;
}
if(str[nxind]<str[ind2]){
num-=p[8-ind2];
no.nx[ind2]--;
}
}
if(dir==3){
int ind1,ind2;
ind1 = xind-1;
ind2 = xind-2;
int cc = 0;
if(str[nxind]>str[ind1])cc++;
if(str[nxind]>str[ind2])cc++;
num = num-p[8-xind]*no.nx[xind] - p[8-nxind]*no.nx[nxind];
tmpcc = no.nx[nxind];
no.nx[nxind]=no.nx[xind] + 3;
no.nx[xind] = tmpcc-cc;
num+=p[8-xind]*no.nx[xind] + p[8-nxind]*no.nx[nxind];
if(str[nxind]<str[ind1]){
num+=p[8-ind1];
no.nx[ind1]++;
}
if(str[nxind]<str[ind2]){
num+=p[8-ind2];
no.nx[ind2]++;
}
}
return num;
}
//右 左 下 上
void restart(char *str,int num,int dir,int xind,int nxind,node &no){
int tmpcc;
if(dir==0){
// num = num-p[8-xind]*no.nx[xind] - p[8-nxind]*no.nx[nxind] + p[8-xind]*(no.nx[nxind]-1) + p[8-nxind]*no.nx[xind];
tmpcc = no.nx[xind];
no.nx[xind]=no.nx[nxind] + 1;
no.nx[nxind] = tmpcc;
}
if(dir==1){
// num = num-p[8-xind]*no.nx[xind] - p[8-nxind]*no.nx[nxind] + p[8-xind]*(no.nx[nxind]+1) + p[8-nxind]*no.nx[xind];
tmpcc = no.nx[xind];
no.nx[xind]=no.nx[nxind] - 1;
no.nx[nxind] = tmpcc;
}
if(dir==2){
int ind1,ind2;
ind1 = xind+1;
ind2 = xind+2;
int cc = 0;
if(str[nxind]>str[ind1])cc++;
if(str[nxind]>str[ind2])cc++;
// num = num-p[8-xind]*no.nx[xind] - p[8-nxind]*no.nx[nxind] + p[8-xind]*(no.nx[nxind]-2) + p[8-nxind]*(no.nx[xind]+cc);
tmpcc = no.nx[xind];
no.nx[xind]=no.nx[nxind] + 3;
no.nx[nxind] = tmpcc-cc;
if(str[nxind]<str[ind1]){
// num+=p[8-ind1];
no.nx[ind1]++;
}
if(str[nxind]<str[ind2]){
//num+=p[8-ind2];
no.nx[ind2]++;
}
}
if(dir==3){
// num = num-p[8-xind]*no.nx[xind] - p[8-nxind]*no.nx[nxind] + p[8-xind]*(no.nx[nxind]+2) + p[8-nxind]*(no.nx[xind]-cc);
int ind1,ind2;
ind1 = xind-1;
ind2 = xind-2;
int cc = 0;
if(str[nxind]>str[ind1])cc++;
if(str[nxind]>str[ind2])cc++;
tmpcc = no.nx[xind];
no.nx[xind]=no.nx[nxind] - 3;
no.nx[nxind] = tmpcc+cc;
if(str[nxind]<str[ind1]){
//num-=p[8-ind1];
no.nx[ind1]--;
}
if(str[nxind]<str[ind2]){
//num=p[8-ind2];
no.nx[ind2]--;
}
}
// return num;
}
void solve(){
//int front,rear;
// if(getnx()&1)
// return false;
int num = getnumber();
int hashnum;
hashnum = charhash("123456789");
node no("123456789",num,hashnum,nx);
no.charstr();
q.push(no);
//vis[num] = true;
int tmpnum,xind,nxind;
int x,y,nx,ny;
while(!q.empty()){
no = q.front();
q.pop();
// num = no.num;
//if(goal==no.hashnum)return true;
xind = no.xind;
if(vis[no.hashnum])continue;
vis[no.hashnum] = true;
//xind = charstr(num);
x = xind/3;
y = xind%3;
for(int i=0;i<4;++i){//右 左 下 上
nx = x + dx[i];
ny = y + dy[i];
if(nx>=0&&nx<3&&ny>=0&&ny<3){
nxind = nx*3+ny;
tmpnum = gethash(no.str,no.hashnum,i,xind,nxind,no);
int cc = no.str[nxind] - '0';
no.str[xind] = no.str[nxind];
no.str[nxind] = '9';
// int chc = charhash(no.str);
int t1,t2;
// t1 = no.num;
t2 = no.hashnum;
if(!vis[tmpnum]){
pa[tmpnum] = no.hashnum;
path[tmpnum] = i;
// int tmpcc = num + (9 - cc)*(pw[nxind]-pw[xind]);
// no.num = tmpcc;
no.hashnum = tmpnum;
no.xind = nxind;
q.push(no);
}
no.str[nxind] = no.str[xind];
no.str[xind] = '9';
// no.num = t1;
no.hashnum = t2;
no.xind = xind;
restart(no.str,no.hashnum,i,xind,nxind,no);
}
}
}
// return false;
}
int getdir(int num){
switch(num){
case 0: return 'l';
case 1: return 'r';
case 2: return 'u';
case 3: return 'd';
}
return 0;
}
void output(bool flag,int hashnum){
if(!flag){
printf("unsolvable\n");
return;
}
int cntans = 0;
int tmp = hashnum;
//char ss[]="ullddrurdllurdruldr";
//printf("%d\n",strlen(ss));
while(1){
if(pa[tmp]==-1)break;
ans[cntans++] = path[tmp];
tmp = pa[tmp];
}
//printf("%d",ans[0]);
// printf("%d\n",cntans);
for(int i=0;i<cntans;++i){
putchar(getdir(ans[i]));
}
printf("\n");
}
void clear(){
while(!q.empty()){
q.pop();
}
}
int main(){
init();
goal = 0;
solve();
//clear();
bool flag;
while(gets(nows)){
flag = true;
prepro();
int hashnum = charhash(nows);
if(!vis[hashnum])flag = false;
output(flag,hashnum);
}
return 0;
}