八数码问题。
BFS+康托展开。康托用来判重。直接搜的的话会超时。需要预处理。
我就用结构体存了一个状态。
struct lx
{
int can;//当前状态的康托展开
int pcan;//上一状态的康托展开
int k;//移动方向
};
把所有的 181442 种状态存下来。排序,然后二分搜索。迭代寻找上一状态,直到初始的 0 。
开始写的时候估计康托逆展开有点问题,一直WA。重写之后就莫名其妙的1A了。
G++ 171ms
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#include<map>
#include<stack>
#include<iostream>
#include<list>
#include<set>
#include<cmath>
#define INF 0x7fffffff
#define eps 1e-8
#define LL long long
#define PI 3.141592654
#define CLR(a,b) memset(a,b,sizeof(a))
#define FORi(n) for(int i=0;i<n;i++)
#define FORj(n) for(int j=0;j<n;j++)
#define FORk(n) for(int k=0;k<n;k++)
#define debug puts("==fuck==")
#define acfun std::ios::sync_with_stdio(false)
#define SIZE 1000+10
using namespace std;
struct lx
{
int can;
int pcan;
int k;
};
int g[4][4]={{1,2,3},{4,5,6},{7,8,9}};
int fac[]={1,1,2,6,24,120,720,5040,40320};
int xx[]={0,0,-1,1};
int yy[]={1,-1,0,0};
lx q[200000]; //max = 181441
bool vis[500000]; //max = 362879
int n;
int cantor()
{
int tmp[10],top=0,num=0;
FORi(3)
FORj(3)
tmp[top++]=g[i][j];
FORi(top)
{
int t=0;
for(int j=i+1;j<top;j++)
if(tmp[j]<tmp[i])t++;
num+=fac[top-i-1]*t;
}
return num;
}
int uncantor(int num)
{
int tmp[10],top=0;
bool v[10];
CLR(v,0);
for(int i=1;i<=9;i++)
{
int t=num/fac[9-i];
num-=t*fac[9-i];
int j=1,k=0;
for(;k<=t;j++)
if(!v[j])k++;
j--;
v[j]=1;
tmp[i-1]=j;
}
int k=0,site;
FORi(3)
FORj(3)
{
g[i][j]=tmp[k++];
if(g[i][j]==9)site=i*3+j;
}
return site;
}
void bfs()
{
int h=0,e=0;
q[h].can=cantor();
q[h].pcan=-1;
q[h++].k=-1;
CLR(vis,0);
vis[0]=1;
while(e<h)
{
int can=q[e++].can;
int site=uncantor(can);
int i=site/3;
int j=site%3;
for(int k=0; k<4; k++)
{
int x=i+xx[k];
int y=j+yy[k];
if(x>=3||x<0||y>=3||y<0)continue;
swap(g[i][j],g[x][y]);
int tmp=cantor();
swap(g[i][j],g[x][y]);
if(vis[tmp])continue;
vis[tmp]=1;
q[h].can=tmp;
q[h].pcan=can;
q[h++].k=k;
n=h;
}
}
}
bool cmp(lx a,lx b)
{
return a.can<b.can;
}
int half(int left,int right,int key)
{
int l=left,r=right;
while(l<r)
{
int m=(l+r)>>1;
if(q[m].can==key)return m;
else if(q[m].can>key)r=m;
else l=m+1;
}
return -2;
}
int main()
{
bfs();
sort(q,q+n,cmp);
char str[11];
while(~scanf("%s",str))
{
if(str[0]>='0'&&str[0]<='8')
g[0][0]=str[0]-'0';
else
g[0][0]=9;
for(int i=1; i<9; i++)
{
scanf("%s",str);
if(str[0]>='0'&&str[0]<='8')
g[i/3][i%3]=str[0]-'0';
else
g[i/3][i%3]=9;
}
int can=cantor();
char out[1001];
int top=0;
bool flag=0;
while(can!=-1)
{
int k=half(0,n,can);
if(k==-2)
{
flag=1;
break;
}
if(q[k].k==0)
out[top++]='l';
else if(q[k].k==1)
out[top++]='r';
else if(q[k].k==2)
out[top++]='d';
else
out[top++]='u';
can=q[k].pcan;
}
if(flag)
puts("unsolvable");
else
{
out[top-1]='\0';
puts(out);
}
}
}
原文:http://blog.csdn.net/dongshimou/article/details/39319895