题意:省略
解题思路:针对八数码问题,如果x往左或往右走,是不会改变逆序数大小的,且往上或往下走只有三种情况,讨论往下走,如果与x交换的数是ai,则要判断的是a(i-1),a(i-2)与ai的关系.
只会出现四种情况,a(i-1)>ai,a(i-2)>ai;逆序对数在原来的基础上+2
a(i-1)
a(i-1)>ai,a(i-2)
a(i-1)
针对上述四种情况,逆序数的初始值为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)
a(i-1)>ai,a(i-2)
a(i-1)
针对上述四种情况,逆序数的初始值为0,则经过各种变换逆序数为偶数,则若一种状态逆序数为奇数,始不可能的。且在保存状态时利用康托展开:X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! (ai为某个数对应的逆序对数,达到状态压缩)。
这里要利用反向的思维,通过最终状态去bfs所有状态。
#include
#include
#include
#include
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;
}
};
queueq;
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;istr[j])tmpc++;
}
nx[i] = tmpc;
ans+=tmpc*p[8-i];
//st++;
}
return ans;
}
int getnx(){
int ans = 0;
for(int i=0;inows[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])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])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])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]=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