状态有9!种,用的全排列的hash。
首先写了个A*算法,0ms过了,但内存消耗挺大。其他方法的代码会陆续添加。
好久没写过这种2500B+的代码。
A*
#include <queue> #include <algorithm> #include <iostream> #define _clr(a,b) memset(a,b,sizeof(a)) using namespace std; const int maxn=362880;//9! const int end_state=0;//{0 1 2 3 4 5 6 7 8}是满足要求的排列,此时state=0 int fac[9],state[9];//fac[i]=i!,fac[0]=0 int move[4]={-1,1,-3,3};//4个方向的移动 int h(int a[])//估价函数,好的估价函数是A*算法的命根 { int ret=0; for(int i=0;i<9;i++) ret+=abs(a[i]-i); return ret; } int get_key(int a[])//全排列的hash,计算状态 { int ret=0,count; for(int i=1;i<9;i++) { count=0; for(int j=0;j<i;j++) count+=a[j]>a[i]?1:0; ret+=count*fac[i]; } return ret; } struct node//插到优先队列中 { int tt[9]; int state; int pos; int step; }start,next; struct node2//存储已经到达过的状态的信息,用于反演路径 { int last_state; int pos; int step; }info[maxn]; bool operator>(const node a,const node b) { return a.step>b.step; } priority_queue<node,vector<node>,greater<vector<node>::value_type>> my_queue; void Init() { fac[0]=0; fac[1]=1; for(int i=2;i<9;i++) fac[i]=fac[i-1]*i; } inline void intcpy(int a[],int b[]) { for(int i=0;i<9;i++) a[i]=b[i]; } bool Find_path() { while(!my_queue.empty()) { start=my_queue.top(); my_queue.pop(); intcpy(next.tt,start.tt); for(int i=0;i<4;i++) { next.pos=start.pos+move[i]; if(abs(move[i])==1&&(next.pos/3!=start.pos/3)) continue;//曾经因为这里,送了n次wa和n个小时的排错时间 if(next.pos>=0&&next.pos<=8) { swap(next.tt[next.pos],next.tt[start.pos]); next.step=h(next.tt); next.state=get_key(next.tt); if(next.state==end_state) { info[next.state].last_state=start.state; info[next.state].pos=next.pos; return true; } if(info[next.state].step==-1) { info[next.state].step=next.step; info[next.state].last_state=start.state; info[next.state].pos=next.pos; my_queue.push(next); } swap(next.tt[next.pos],next.tt[start.pos]); } } } return false; } char move2[maxn]; int index; void Output() { index=0; int kk=end_state,tt,diff; while((tt=info[kk].last_state)>=0)//反演路径 { diff=info[tt].pos-info[kk].pos; if(diff==3) move2[index]='u'; else if(diff==1) move2[index]='l'; else if(diff==-1) move2[index]='r'; else if(diff==-3) move2[index]='d'; else printf("/nwrong/n"); index++; kk=tt; } for(int i=index-1;i>=0;i--) printf("%c",move2[i]);//输出路径 printf("/n"); } int main() { freopen("e://1.in","r",stdin); freopen("e://1.out","w",stdout); Init(); _clr(info,-1); char for_input[5]; int first=0,count=0; for(int i=0;i<9;i++) { scanf("%s",for_input); if(for_input[0]=='x') start.tt[i]=8,start.pos=i; else start.tt[i]=for_input[0]-'0'-1; } first=get_key(start.tt); if(first==end_state) { printf("/n"); return 0; } info[first].last_state=-1; info[first].pos=start.pos; start.step=info[first].step=h(start.tt); start.state=first; my_queue.push(start); if(Find_path()) Output(); else printf("unsolvable/n"); return 0; }