problem
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 x
1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8
9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12
13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x
r-> d-> r->
Input
1 2 3
x 4 6
7 5 8
1 2 3 x 4 6 7 5 8
Output
You will print to standard output either the word “unsolvable”, if the puzzle has no solution, or a string consisting entirely of the letters ‘r’, ‘l’, ‘u’ and ‘d’ that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line.
Sample Input
2 3 4 1 5 x 7 6 8
Sample Output
ullddrurdllurdruldr
solution
将x看做9,那这样是一个1~9的排列,状态共有 9!=362880 9 ! = 362880 种
考虑爆搜(bfs) 每一次上下左右交换后就是排列的改变,关键问题在于排列的判重,自然想到康拓展开
时间复杂度 O(9!∗92) O ( 9 ! ∗ 9 2 ) 其中 92 9 2 为康托展开求散列值
code example
#include<iostream>
#include<queue>
#include<string.h>
#include<cstdio>
using namespace std;
int debug_num=0;
#define debug cout<<"debug "<<++debug_num<<" :"
const int maxn=5e5;
int fac[10];
bool vis[maxn];
struct node{
char mapp[4][4];
int Hash;
int x,y;
string path;
};
int dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}};
char walk[5]="lrdu";
node sta;
void init()
{
fac[0]=fac[1]=1;
for(int i=2;i<=9;++i) fac[i]=fac[i-1]*i;
}
int array_to_int(const node &s)//散列
{
int ans=0;
for(int i=1;i<=9;++i){
int temp=0;
for(int j=i+1;j<=9;++j) {
if(s.mapp[(j-1)/3+1][(j-1)%3+1]<s.mapp[(i-1)/3+1][(i-1)%3+1]) ++temp;
}
ans+=temp*fac[9-i];
}
return ans;
}
int aim=0;//目标的散列值
string ans_path;
bool bfs()
{
memset(vis,false,sizeof(vis));
queue<node> q;
q.push(sta);
node now,next;
while(!q.empty())
{
now=q.front();
//if(debug_num<10000) debug<<now.x<<" "<<now.y<<" "<<now.path<<endl;
q.pop();
if(now.Hash==aim){
ans_path=now.path;
return true;
}
for(int i=0;i<4;++i){
int tx=now.x+dir[i][0];
int ty=now.y+dir[i][1];
if(tx<1||tx>3||ty<1||ty>3) continue;
next=now;
next.x=tx;
next.y=ty;
swap(next.mapp[tx][ty],next.mapp[now.x][now.y]);
next.Hash=array_to_int(next);
if(!vis[next.Hash]){
vis[next.Hash]=true;
next.path=next.path+walk[i];
q.push(next);
if(next.Hash==aim){
ans_path=next.path;
return true;
}
}
}
}
return false;
}
int main()
{
freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
init();
for(int i=1;i<=3;++i)
for(int j=1;j<=3;++j){
char c;
cin>>c;
if(c=='x'){
sta.x=i,sta.y=j;
sta.mapp[i][j]='9';//将x当为9
}
else sta.mapp[i][j]=c;
}
sta.Hash=array_to_int(sta);
if(bfs()){
cout<<ans_path<<endl;
}
else cout<<"unsolvable"<<endl;
cout<<fac[9]<<endl;
return 0;
}