题意: 八数码。给一个初始状态,然后让你还原回去,问最小步数,且打印路径。
题解: 直接bfs 超时,那就用A*, 哈曼顿距离f+g在队列中优先选择f+g最小的判断,能够加快广搜的搜索速度。标记用康托。
另外,如果就像逆序数一样,如果来是和结尾的两个状态逆序数不同就不可能成功。否则可以。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <queue>
int a[10],f;
using namespace std;
struct node{
int ma[3][3];
int tx,ty;
int hash_val;
string way;
int g,f;
bool operator< (const node &a) const{
return f>a.f;
}
}ed,sta,e,u,q;
priority_queue<node>que;
int hash_tab[370000];
int fn[10]={1};
int ed_map[10][2];
int dir[4][2]={1,0,0,1,-1,0,0,-1};
char w[]="drul";
bool judge(int x,int y){
if(x<0||x>2||y<0||y>2) return 0;
return 1;
}
void get_m(char st[]){
int cnt=0,len=strlen(st);
for(int i=0;i<len;++i){
if(st[i]>'0'&&st[i]<='9') a[cnt++]=st[i]-'0';
if(st[i]=='x') {
a[cnt++]=0;
sta.tx=(cnt-1)/3;
sta.ty=(cnt-1)%3;
}
}
cnt=0;
for(int i=0;i<3;++i)
for(int j=0;j<3;++j)
ed.ma[i][j]=i*3+j+1,sta.ma[i][j]=a[cnt++];
ed.ma[2][2]=0;
for(int i=0;i<3;++i){
for(int j=0;j<3;++j){
sta.ma[i][j]=a[i*3+j];
if(ed.ma[i][j]) ed_map[ed.ma[i][j]][0]=i,ed_map[ed.ma[i][j]][1]=j;
}
}
}
int get_hash(node aa){
int ret=0,num=8,x;
for(int i=0;i<3;++i){
for(int j=0;j<3;++j){
x=0;
for(int k=j+1;k<3;++k)
if(aa.ma[i][j]>aa.ma[i][k]) x++;
for(int l=i+1;l<3;++l)
for(int k=0;k<3;++k)
if(aa.ma[i][j]>aa.ma[l][k]) x++;
ret+=fn[num]*x;
num--;
}
}
return ret;
}
int get_f(node a,int g){
int h=0;
for(int i=0;i<3;++i)
for(int j=0;j<3;++j)
if(a.ma[i][j]) h+=abs(i-ed_map[a.ma[i][j]][0])+abs(j-ed_map[a.ma[i][j]][1]);
return g+h;
}
void exc(node &e,node b){
swap(e.ma[e.tx][e.ty],e.ma[b.tx][b.ty]);
e.hash_val=get_hash(e);
e.g=b.g+1;
e.f=get_f(e,e.g);
}
void bfs(){
while(!que.empty()) que.pop();
sta.hash_val=get_hash(sta);
ed.hash_val=get_hash(ed);//cout<<sta.hash_val<<" "<<ed.hash_val<<endl;
sta.f=get_f(sta,0);
sta.g=0;
hash_tab[sta.hash_val]=1;
que.push(sta);
if(sta.hash_val!=ed.hash_val)
while(!que.empty()){ //cout<<"@!@"<<endl;
u=que.top();
que.pop();
for(int i=0;i<4;++i){
int tx=u.tx+dir[i][0];
int ty=u.ty+dir[i][1];
if(judge(tx,ty)){
e=u;
e.tx=tx,e.ty=ty;
exc(e,u);
e.way+=w[i];
if(hash_tab[e.hash_val]) continue;
if(e.hash_val==ed.hash_val){
f=1; break;
}
que.push(e);
}
}
if(f) break;
hash_tab[u.hash_val]=1;
}
cout<<e.way<<endl;
}
int get_inv(node ss){
int ret=0;
for(int i=0;i<3;++i){
for(int j=0;j<3;++j){
if(!ss.ma[i][j]) continue;
int sum=0;
for(int k=j+1;k<3;++k)
if(ss.ma[i][k]&&ss.ma[i][k]<ss.ma[i][j]) sum++;
for(int l=i+1;l<3;++l)
for(int k=0;k<3;++k)
if(ss.ma[l][k]&&ss.ma[l][k]<ss.ma[i][j]) sum++;
ret+=sum;
}
}
return ret%2;
}
int main(){
char str[30];
for(int i=1;i<9;++i) fn[i]=i*fn[i-1];
while(gets(str)){
f=0;memset(hash_tab,0,sizeof(hash_tab));
get_m(str);
if(get_inv(sta)^get_inv(ed)) puts("unsolvable");
else bfs();
}
return 0;
}