BFS之三(单向bfs和康托压缩)
//poj 1077 Eight
#include <iostream> //单向bfs和康托压缩
#include<string>
using namespace std;
bool visited[1000000];
int fac[]={1,1,2,6,24,120,720,5040,40320,362880}; //9!表
int cantor(int arr[])
{
int temp,num=1; //当排列为1 2 3 4 5 6 7 8 9时康托值等于1
for(int i=0;i<9;++i)
{
temp=0;
for(int j=i+1;j<9;++j)
if(arr[j]<arr[i])
temp++;
num+=fac[8-i]*temp;
}
return num;
}
void to_arr(int list[],int num)
{
int i;
for(i=0;i<9;++i)
list[i]=0;
i=8;
while(num)
{
list[i--]=num%10;
num/=10;
}
}
int to_num(int list[])
{
int n=0;
for(int i=0;i<9;++i)
n=n*10+list[i];
return n;
}
struct node
{
char ch;
int pre; //通过pre记录路径,这样就不需开个string记录之前所走过的全部路径
int num; //通过num与arr相互转换,这样就不需开个数组记录当前的状态
int sub;
};
node table[1000000];
//程序的空间开销是3348K,但单向bfs的运行时间会较多
int move[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
char pos[4]={'d','r','u','l'};
int main()
{
int arr[9];
char ch;
for(int i=0;i<9;++i)
{
cin>>ch;
if(ch=='x')
arr[i]=9,table[0].sub=i;
else
arr[i]=int(ch-48);
}
table[0].pre=-1;table[0].num=to_num(arr);
visited[cantor(arr)]=1;
int head=0,rear=0;
while(head<=rear)
{
to_arr(arr,table[head].num);
if(cantor(arr)==1) //当排列为1 2 3 4 5 6 7 8 9时康托值等于1
{
string str;
int i=head;
while(i!=0)
{
str.insert(str.begin(),table[i].ch);
i=table[i].pre;
}
cout<<str<<endl;
return 0;
}
int x,y,tx,ty;
x=table[head].sub/3;y=table[head].sub%3;
for(int i=0;i<4;++i)
{
tx=x+move[i][0];ty=y+move[i][1];
if(tx>=0&&tx<3&&ty>=0&&ty<3)
{
swap(arr[x*3+y],arr[tx*3+ty]);
if(visited[cantor(arr)]==0)
{
++rear;
table[rear].num=to_num(arr);
table[rear].ch=pos[i];
table[rear].pre=head;
table[rear].sub=tx*3+ty;
visited[cantor(arr)]=1;
}
swap(arr[x*3+y],arr[tx*3+ty]);
}
}
head++;
}
cout<<"unsolvable\n";
return 0;
}