八数码之八重境界http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html
关键在于利用康托展开判重
发现自己模拟的队列比STL中queue快
#include<stdio.h>
#include<string.h>
#include<string>
#include<algorithm>
#include<iostream>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<math.h>
#include<stdlib.h>
#define M 400000
using namespace std;
struct stu
{
char s[20];
int pos;
}st,ed,dl[M];
struct pa
{
int fa;
char c;
}path[M];
int mark[M];
int jc[12];
int h[4]={-1,0,1,0};
int z[4]={0,1,0,-1};
char fa[]={"urdl"},pstr[M];
void getjc()//阶乘
{
int i,j,k;
jc[0]=1;
for(i=1;i<12;i++)
jc[i]=jc[i-1]*i;
}
int getkt(char s[20])//康托展开
{
int i,j,k,len,an[20],ans=0;
getjc();
len=strlen(s);
memset(an,0,sizeof(an));
for(i=0;i<len;i++)//获得当前未出现的比他小的数,即它右边有几个比他小的数
for(j=0;j<i;j++)
{
if(s[j]>s[i])
an[j]++;
}
for(i=0;i<len;i++)//康托公式运算
{
ans+=an[i]*jc[len-i-1];
}
return ans;
}
void prin(char s[20])
{
int i,j;
for(i=0;i<9;i++)
{
if(i%3==0)
puts("");
printf("%c ",s[i]);
}
}
void getnikc(int len,int xu)//逆康托
{
int i,j,k;
int xs[20],js[20];
char s[20];
getjc();
for(i=len-1,j=0;i>=0;i--,j++)//辗转相除,得到an
{
xs[j]=xu/jc[i];
if(xu!=0)
xu=xu%jc[i];
js[i]=1;
}
for(i=0;i<len;i++)//找剩下子集中的第xs[i]大元素
{
int t=0;
for(j=0;j<len;j++)
{
t+=js[j];
if(t>xs[i])
{
s[i]='0'+j;
js[j]=0;
break;
}
}
}
s[len]='\0';
prin(s);
}
int judge(int x,int y)
{
return (x>=0&&x<3&&y>=0&&y<3);
}
int bfs()
{
int i,j,k,r,f,x,y,t;
char s[20];
char c;
memset(mark,0,sizeof(mark));
r=f=0;
dl[0]=st;
k=getkt(st.s);
mark[k]=1;
path[k].fa=k;
// printf("st kt %d\n",k);
while(r<=f)
{
k=getkt(dl[r].s);
if(k==ed.pos)
return k;
for(i=0;i<4;i++)
{
stu nw;
strcpy(nw.s,dl[r].s);
int p=dl[r].pos;
x=p/3;
y=p%3;
// printf("qian x=%d,y=%d %d\n",x,y,p);
x=x+h[i];
y=y+z[i];
// printf("hou x=%d,y=%d %d\n",x,y,x*3+y);
if(judge(x,y))
{
t=x*3+y;
c=nw.s[p];
nw.s[p]=nw.s[t];
nw.s[t]=c;
nw.pos=t;
t=getkt(nw.s);
if(mark[t]==0)
{
dl[++f]=nw;
path[t].fa=k;
path[t].c=fa[i];
mark[t]=1;
}
}
}
r++;
}
return -1;
}
int main()
{
// freopen("1077.in","r",stdin);
// freopen("1077.out","w",stdout);
int i,j,k;
char c;
for(i=0;i<9; )
{
scanf("%c",&c);
if(c == 'x')
{
st.s[i]='0';
st.pos=i;
i++;
}
else if(c>='0'&&c<='9')
{
st.s[i] = c;
i++;
}
else
continue;
}
st.s[9]='\0';
// printf("aaa %s %d\n",st.s,st.pos);
// while(1)
{
/*
scanf("%s",st.s);
for(i=0;i<9;i++)
{
if(st.s[i]=='x')
{
st.pos=i;
st.s[i]='0';
}
}*/
strcpy(ed.s,"123456780");
ed.pos=getkt(ed.s);
// printf("ed.p %d\n",ed.pos);
int ans=bfs();
if(ans==-1)
{
puts("unsolvable");
}
else
{
i=0;
// getnikc(9,ans);
while(ans!=path[ans].fa)
{
// printf("\nans %d fa %d\n",ans,path[ans].fa);
// printf("%c",path[ans].c);
pstr[i++]=path[ans].c;
ans=path[ans].fa;
// getnikc(9,ans);
}
pstr[i]='\0';
// puts("");
reverse(pstr,pstr+i);
puts(pstr);
}
}
return 0;
}
/*
23415x768
*/