解题分析过程见hdu1043八数码问题解题报告
//1043双向搜索-八数码 #include <iostream> #include <string> #include <queue> using namespace std; char input[100]; int state[10],s_num,e10[10],fac_n[10]; char hash_T[400000],step[10000],hash_T2[400000]; struct inf { int pos; char mode; }; queue<inf> SQ; queue<inf> SQ2; inline int move(int num,char op); bool be_solved(); inline int hash(int num); void BFS2(); int main() { int i,j; for(e10[0]=1,i=1;i<=9;i++) e10[i]=e10[i-1]*10; for(fac_n[0]=0,fac_n[1]=1,i=2;i<=9;i++) fac_n[i]=fac_n[i-1]*i; while(gets(input)) { for(i=strlen(input)-1,j=8;i>=0;i--) { if(input[i]!=' ') { if(input[i]=='x') state[9]=j+1; else state[j--]=input[i]-'0'; } } for(s_num=0,i=9,j=1;i>0;i--,j*=10) s_num+=state[i]*j; if(!be_solved()) printf("unsolvable\n"); else { BFS2(); printf("\n"); } } return 0; } bool be_solved() { int i,j,anti=0; for(i=1;i<=8;i++) for(j=1;j<i;j++) if(state[i]<state[j]) anti++; if(anti%2)return 0; else return 1; } void BFS2() { int to_num,to_hash,i; char *phash,*phash2; char op; inf k,t; memset(hash_T,0,sizeof(hash_T)); memset(hash_T2,0,sizeof(hash_T2)); while(!SQ2.empty()) SQ2.pop(); k.pos=s_num;k.mode=1; SQ2.push(k); k.pos=123456789;k.mode=2; SQ2.push(k); hash_T[hash(s_num)]='s'; hash_T2[hash(123456789)]='e'; while(!SQ2.empty()) { k=SQ2.front(); SQ2.pop(); to_hash=hash(k.pos); if(k.mode==1) if(hash_T2[to_hash]!=0)break; else phash=hash_T,phash2=hash_T2; if(k.mode==2) if(hash_T[to_hash]!=0)break; else phash=hash_T2,phash2=hash_T; t=k; t.pos=move(k.pos,'r'); to_hash=hash(t.pos); if(to_hash>=0&&phash[to_hash]==0) phash[to_hash]='r',SQ2.push(t); t.pos=move(k.pos,'l'); to_hash=hash(t.pos); if(to_hash>=0&&phash[to_hash]==0) phash[to_hash]='l',SQ2.push(t); t.pos=move(k.pos,'u'); to_hash=hash(t.pos); if(to_hash>=0&&phash[to_hash]==0) phash[to_hash]='u',SQ2.push(t); t.pos=move(k.pos,'d'); to_hash=hash(t.pos); if(to_hash>=0&&phash[to_hash]==0) phash[to_hash]='d',SQ2.push(t); } i=0; to_hash=hash(k.pos); to_num=k.pos; while(hash_T[to_hash]!='s') { switch(step[i++]=hash_T[to_hash]) { case 'r': op='l';break; case 'l': op='r';break; case 'u': op='d';break; case 'd': op='u';break; } to_num=move(to_num,op); to_hash=hash(to_num); } while(i>0)printf("%c",step[--i]); to_hash=hash(k.pos); to_num=k.pos; while(hash_T2[to_hash]!='e') { switch(hash_T2[to_hash]) { case 'r': op='l';break; case 'l': op='r';break; case 'u': op='d';break; case 'd': op='u';break; } printf("%c",op); to_num=move(to_num,op); to_hash=hash(to_num); } } inline int hash(int num) { int dig[10],i=9,j,sum,anti; if(num==0)return -1; while(num) dig[i]=num%10,num/=10,i--; sum=(9-dig[9])*fac_n[8]; for(i=1;i<9;i++) { for(anti=0,j=1;j<i;j++) if(dig[i]<dig[j]) anti++; sum+=anti*fac_n[i-1]; } return sum; } inline int move(int num,char op) { int t0,t1,t2; switch(op) { case 'r': if(num%10%3==0)return 0; return num+1; case 'l': if((num-1)%10%3==0)return 0; return num-1; case 'u': if(num%10-3<=0)return 0; t0=9-num%10+1; t1=num/e10[t0]; t2=t1%1000; t1=t1-t2+(t2%100)*10+t2/100; t1*=e10[t0]; return (t1+((num%e10[t0])-3)); case 'd': if(num%10+3>9)return 0; t0=9-num%10+1-3; t1=num/e10[t0]; t2=t1%1000; t1=t1-t2+(t2%10)*100+t2/10; t1*=e10[t0]; return (t1+((num%e10[t0])+3)); } }