双向BFS
这题需要特判无法变换到得情况,我们发现每次变换8个数字的逆序数奇偶性都是不变的,所以找出给定的序列的逆序数可以特判不存在的情况。
康托展开:http://www.cnblogs.com/hxsyl/archive/2012/04/11/2443009.html
开个结构体node2存当前的string,并且存它的x出现在哪个位置,然后把string康托展开得到一个数p当作是这个string的编号,vis[p]就是当前这个是第几个字符串
开个结构体数组存第k字符串的前一个的编号是多少,然后再存下操作是什么。
之后是双向BFS,跟单BFS用的一样,从开头和终点一起开始BFS,直到两个BFS相遇,就是最短的路程了。这样可以缩短很长的时间,why?例如一个迷宫,我们假设没有边界,没有墙的空地,单BFS需要4^n时间,那双向BFS就是4^(n/2)*2,缩短了很多。
(A*算法并不懂,改天再学,这个就当熟悉一下康托展开和双向BFS了)
#include <iostream>
#include <cstdio>
#include <cctype>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <sstream>
#include <stack>
using namespace std;
#define MAX 1000000+5
#define MAXN 100000+5
typedef long long LL;
const double pi=3.141592653589793;
const int INF=0x3f3f3f3f;
const int INFF=1e9;
const double inf=1e18;
const double eps=1e-10;
const int mod=1000000007;
int dir[4]={-3,3,-1,1};
char d1[10]={"udlr"};
char d2[10]={"durl"};
int hhash[9]={1,1,2,6,24,120,720,5040,40320};
int vis[MAX];
int vis2[MAX];
struct node{
int num;
char d;
}pre[MAX];
struct node2{
string c;
int num;
}e;
string s="123456780";
int get_hash(string s){
int temp=0;
int len=s.size();
for(int i=0;i<len-1;i++){
int k=0;
for(int j=i+1;j<len;j++){
if(s[i]>s[j]) k++;
}
temp+=k*hhash[len-1-i];
}
return temp;
}
void show(int x){
if(pre[x].num==-1) return ;
show(pre[x].num);
printf("%c",pre[x].d);
}
void bfs(){
queue<node2> q1;
queue<node2> q2;
node2 f,g;
f.c=s;
f.num=8;
vis[get_hash(e.c)]=1;
pre[1].num=-1;
vis2[get_hash(f.c)]=2;
pre[2].num=-1;
int num=2;
q1.push(e);
q2.push(f);
while(!q1.empty()&&!q2.empty()){
f=q1.front();
q1.pop();
int p=get_hash(f.c);
if(vis2[p]){
show(vis[p]);
int k=vis2[p];
while(pre[k].num!=-1){
printf("%c",pre[k].d);
k=pre[k].num;
}
printf("\n");
return;
}
for(int i=0;i<4;i++){
if(i==0&&f.num<3)continue;
if(i==1&&f.num>5)continue;
if(i==2&&f.num%3==0)continue;
if(i==3&&f.num%3==2)continue;
int x=f.num+dir[i];
g=f;
swap(g.c[f.num],g.c[x]);
int q=get_hash(g.c);
if(!vis[q]){
vis[q]=++num;
g.num=x;
pre[num].num=vis[p];
pre[num].d=d1[i];
q1.push(g);
}
}
f=q2.front();
q2.pop();
p=get_hash(f.c);
if(vis[p]){
show(vis[p]);
int k=vis2[p];
while(pre[k].num!=-1){
printf("%c",pre[k].d);
k=pre[k].num;
}
printf("\n");
return;
}
for(int i=0;i<4;i++){
if(i==0&&f.num<3)continue;
if(i==1&&f.num>5)continue;
if(i==2&&f.num%3==0)continue;
if(i==3&&f.num%3==2)continue;
int x=f.num+dir[i];
g=f;
swap(g.c[f.num],g.c[x]);
int q=get_hash(g.c);
if(!vis2[q]){
vis2[q]=++num;
g.num=x;
pre[num].num=vis2[p];
pre[num].d=d2[i];
q2.push(g);
}
}
}
printf("unsolvable\n");
}
int main(){
char a[30];
while(gets(a)){
int n=strlen(a);
e.c="";
for(int i=0,j=0;i<n;i++){
if(a[i]!=' '){
if(a[i]=='x'){
e.num=j;
e.c=e.c+'0';
}
else e.c=e.c+a[i];
j++;
}
}
memset(vis,0,sizeof(vis));
memset(vis2,0,sizeof(vis2));
int k=0;
for(int i=0;i<9;i++){
if(e.c[i]=='0') continue;
for(int j=0;j<i;j++){
if(e.c[j]=='0') continue;
if(e.c[j]>e.c[i]) k++;
}
}
if(k%2) printf("unsolvable\n");
else bfs();
}
return 0;
}