hdu 1043 八数码--打表
http://acm.hdu.edu.cn/showproblem.php?pid=1043
题意:略;
思路:其实怎么看也是打表的思路比较容易想一些,不过A*搜索真是神奇。。。而且打表快不少,可能和多组数据有关,其实A*也可以记忆化一下应付一下多组数据,大概也会快不少吧。。。
思路很简单,从最终状态反向暴力BFS就可以了。。因为所有状态也已9!不是很多,主要用hash来去重就可以了。思维含量比A*简单。。
代码:
#include <bits/stdc++.h>
using namespace std;
const int dis[12] = {1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800};
int tmp[10];
char s[10];
const int maxn=1e5*4;
int arr[10];
int vis[maxn];
int last[maxn+10];
int how[maxn+10];
int ans=-1;
int Cantor(int x, int len){
int c=0;
while(x){
tmp[c++]=x%10;
x/=10;
}
int resl = 1;
for(int i = 0; i < len; i++){
int counts = 0;
for(int k = i + 1; k < len; k++){
if(tmp[i] > tmp[k]){
counts++;
}
}
resl = resl + dis[len-i-1] * counts;
}
return resl;
}
int tran(int x,int h){
int c=0,ret=0,idx=0;;
while(x){
tmp[c++]=x%10;
if(tmp[c-1]==9) idx=c-1;
x/=10;
}
if(h==0){
if(idx<3) return -1;
else swap(tmp[idx],tmp[idx-3]);
}
else if(h==1){
if(idx%3==2) return -1;
else swap(tmp[idx],tmp[idx+1]);
}
else if(h==2){
if(idx>5) return -1;
else swap(tmp[idx],tmp[idx+3]);
}
else if(h==3){
if(idx%3==0) return -1;
else swap(tmp[idx],tmp[idx-1]);
}
for(int i=0,j=1;i<9;i++,j*=10) ret+=tmp[i]*j;
return ret;
}
struct node{
int num,id;
node(){};
node(int b,int c):num(b),id(c){};
};
bool Astar(){
memset(vis,-1,sizeof(vis));
memset(last,-1,sizeof(last));
queue<node> P;
int x=0,cnt=0;
for(int i=0,j=1;i<9;i++,j*=10) x+=arr[i]*j;
P.push(node(x,cnt++));
vis[Cantor(x,9)]=1;
while(!P.empty()){
node t=P.front();
P.pop();
ans=t.id;
for(int i=0;i<4;i++){
int x=tran(t.num,i);
if(x!=-1&&vis[Cantor(x,9)]==-1){
vis[Cantor(x,9)]=cnt;
last[cnt]=t.id;
how[cnt]=i;
P.push(node(x,cnt++));
}
}
}
return false;
}
char re[maxn];
void pr(int x){
int c=0;
while(x!=0){
if(how[x]==0) re[c++]='d';
else if(how[x]==1) re[c++]='l';
else if(how[x]==2) re[c++]='u';
else if(how[x]==3) re[c++]='r';
x=last[x];
}
for(int i=0;i<c;i++) printf("%c",re[i]);
puts("");
}
int main(){
for(int i=0;i<9;i++) arr[i]=i+1;
Astar();
while(cin>>s[0]>>s[1]>>s[2]>>s[3]>>s[4]>>s[5]>>s[6]>>s[7]>>s[8]){
for(int i=0;i<9;i++){
if(s[i]=='x') arr[i]=9;
else arr[i]=(int)(s[i]-'0');
}
int ret=0;
for(int i=0,j=1;i<9;i++,j*=10) ret+=arr[i]*j;
if(ret==987654321) puts("");
else if(vis[Cantor(ret,9)]!=-1){
pr(vis[Cantor(ret,9)]);
}
else{
puts("unsolvable");
}
}
return 0;
}