Poj1077/HDU1043(A*搜索)八数码问题

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043

             http://poj.org/problem?id=1077

 

题意:经典的八数码问题,问给出的一个状态能否通过移动达到一个目标状态,如果能就输出一个可行的移动方式.

 

 

看过好几本书上面都有八数码问题的介绍,采用A*搜索,可一开始写的用不在目标位置上的方块个数作为h(n),可一直超时~

 

然后改成各个方块到目标状态的曼哈顿距离,在北大OJ上AC了,尴尬的是HDU上给了整整五倍的时间,还是超时了,今天去图书管看看新书有没有到,然后又翻了翻以前看过的一本算法书籍,看到了一个高效的估价函数,即

 

           h(n)=d(n)+3*g(n)

 

  其中d(n)为各方块到目标状态的曼哈顿矩离,g(n)为非中心的每个方块的后继是否为其目标状态的后继,如果不是,g(n)+=2,最后如果中间位置的方块和目标状态不同g(n)+=1;

 

结果是,原来在POJ上700+msAC的代码,时间一下子降到了32ms~   不过郁结的是在HDU上还是花费500+ms的时间 ...

 

 

代码:

#pragma warning (disable:4786) #include<iostream> #include<string> #include<queue> #include<map> using namespace std; const char board[][3]={'1','2','3','4','5','6','7','8','9'}; const short next[10]={0,2,3,6,1,0,9,4,7,8};//记录目标状态后继 const short point[][2]={{0,0},{0,1},{0,2},{1,2},{2,2},{2,1},{2,0},{1,0}}; typedef struct talQ{ char board[3][3]; int x,y; int v,t; string s; bool operator < (const talQ &a)const {return (a.v+a.t)<(v+t);} }Q; Q start; string ans; priority_queue<Q>q; bool flag; short dir[][2]={{0,1},{0,-1},{1,0},{-1,0}}; char com[]="rldu"; map<int,int>mem; short abs(short a) {return a>0?a:-a;} int Hash(char s[][3]) { int key=0; short i,j; for(i=0;i<3;i++){ for(j=0;j<3;j++){ key*=10; key+=s[i][j]-'0'; } }return key; } short Value(char s[][3]) { short i,j,c=0,g=0; /*原估价函数 for(i=0;i<3;i++){ for(j=0;j<3;j++) c+=(abs((s[i][j]-'1')/3-i)+abs((s[i][j]-'1')%3-j)); } */ for(i=0;i<3;i++){ for(j=0;j<3;j++) c+=(abs((s[i][j]-'1')/3-i)+abs((s[i][j]-'1')%3-j)); } for(i=0;i<8;i++){//增添部分 if(s[point[(i+1)%8][0]][point[(i+1)%8][1]]!= next[s[point[i][0]][point[i][1]]-'0']+'0') g+=2; } if(s[1][1]!=board[1][1]) g++; return c+3*g; } short Caunt(char s[][3]) { short i,j,c=0,k; short tmp[9]; k=0; for(i=0;i<3;i++){ for(j=0;j<3;j++) if(s[i][j]!='9') tmp[k++]=s[i][j]; } for(i=0;i<k;i++){ for(j=i+1;j<k;j++) if(tmp[i]<tmp[j])c++; } return c; } bool Wall(int x,int y) { return x<0||x>2||y<0||y>2; } void FindPath() { short i; Q cur,next; flag=false; if(start.v==0){flag=true;ans="";return;} while(!q.empty()) q.pop(); mem.clear(); q.push(start); mem[Hash(start.board)]=1; while(!q.empty()){ cur=q.top();q.pop(); for(i=0;i<4;i++){ next.x=cur.x+dir[i][0]; next.y=cur.y+dir[i][1]; if(Wall(next.x,next.y)) continue; next.t=cur.t+1; next.s=cur.s+com[i]; memmove(next.board,cur.board,sizeof(board)); next.board[cur.x][cur.y]=next.board[next.x][next.y]; next.board[next.x][next.y]='9'; next.v=Value(next.board); if(next.v==0) { flag=true; ans=next.s; return; } if(mem[Hash(next.board)]==1) continue; mem[Hash(next.board)]=1; q.push(next); } } } bool Read() { char c[2],i,j; start.v=0; for(i=0;i<3;i++){ for(j=0;j<3;j++){ if(scanf("%s",c)==EOF) return false; if(c[0]=='x') { start.board[i][j]='9'; start.x=i;start.y=j; } else start.board[i][j]=c[0]; } } start.s="";start.t=0;start.v=Value(start.board); return true; } int main() { while(Read()){ if(Caunt(start.board)&1){ cout<<"unsolvable"<<endl; continue; } FindPath(); cout<<(flag?ans:"unsolvable")<<endl; } return 0; }  

你可能感兴趣的:(c,算法,struct,qq)