A*算法实现 八数码问题
有关八数码问题及其参考:
http://wenku.baidu.com/view/87c92ef1ba0d4a7302763a29.html
http://blog.csdn.net/damotiansheng/article/details/40017107
http://blog.csdn.net/wsywl/article/details/5726617
下面的代码实现可以在poj上验证其正确性,估价函数可以进行修改.
poj 原题网址:http://bailian.openjudge.cn/practice/1077
1 #include <iostream> 2 #include <map> 3 #include <algorithm> 4 #include <string> 5 #include <queue> 6 #include <set> 7 using namespace std; 8 typedef long long LL; 9 10 int eight[3][3], xx, xy, dx[]={0,-1,1,0}, dy[]={1,0,0,-1}; 11 char dir[] = "rudl"; 12 LL init, tar; 13 14 LL encode(){ 15 LL s=eight[2][2]; 16 for(int i=7; i>=0; --i){ 17 s <<=4; 18 s |= eight[i/3][i%3]; 19 } 20 return s; 21 } 22 void decode(LL s){ 23 for(int i=0; i<9; ++i){ 24 eight[i/3][i%3] = s%16; 25 if(s%16 == 0) 26 xx = i/3, xy = i%3; 27 s >>=4; 28 } 29 } 30 class Node { 31 public: 32 LL s, ps; 33 int f,g,h,d; 34 Node (LL _s=0, LL _ps=0, int _d=-1, int _f=0, int _g=0, int _h=0){ 35 s = _s, ps = _ps, f = _f, g = _g, h = _h, d = _d; 36 } 37 int operator<(const Node & b) const { 38 return this->f < b.f || (this->f==b.f && this->s<b.s); 39 } 40 }; 41 42 multiset<Node> closed, open; 43 map<LL, multiset<Node>::iterator> inOpen, inClosed; 44 45 void print(Node nd){ 46 int d = nd.d; 47 LL ts = nd.s; 48 string ope; 49 while(d!=-1){ 50 ope.push_back(dir[d]); 51 auto itc = inClosed[nd.ps]; 52 nd = *itc; 53 d = nd.d; 54 } 55 reverse(ope.begin(), ope.end()); 56 cout<< ope<< "\n"; 57 } 58 int hn(LL s){ 59 decode(s); 60 int cnt=0; 61 for(int i=0; i<9; ++i){ 62 if(eight[i/3][i%3] != (i+1)%9) cnt++; 63 } 64 return cnt; 65 } 66 void astar(){ 67 init = encode(); 68 int inith = hn(init); 69 Node start = Node(init, 0, -1, inith, 0, inith); 70 open.insert(start); 71 while(!open.empty()){ 72 Node tn = *open.begin(); inOpen.erase(tn.s); open.erase(tn); 73 LL ts = tn.s, s2; 74 int tf = tn.f, tg = tn.g, th = tn.h; 75 for(int i=0; i<4; ++i){ 76 decode(ts); 77 int r = xx+dx[i], c=xy+dy[i]; 78 if(r<0 || c<0 || r==3 || c==3) continue; 79 swap(eight[r][c], eight[xx][xy]); 80 s2 = encode(); 81 int g = tg+1, h = hn(s2), f = g+h; 82 Node nd = Node(s2, ts, i, f, g, h); 83 if(s2 == tar){ 84 inClosed[tn.s]= closed.insert(tn); 85 inClosed[nd.s]= closed.insert(nd); 86 print(nd); 87 return; 88 } 89 auto ito = inOpen.find(s2), itc = inClosed.find(s2); 90 if(ito == inOpen.end() && itc == inClosed.end()){ 91 inOpen[nd.s]=open.insert(nd); 92 } 93 else if(ito == inOpen.end() && f < itc->second->f){ 94 closed.erase(itc->second); inClosed.erase(itc); 95 inOpen[nd.s]=open.insert(nd); 96 } 97 else if(itc == inClosed.end() && f < ito->second->f){ 98 // que 里有相同s不同f的node 99 open.erase(ito->second), inOpen[nd.s]=open.insert(nd); 100 } 101 } 102 inClosed[tn.s] = closed.insert(tn); 103 } 104 } 105 int main(){ 106 std::ios::sync_with_stdio(false); 107 char c; 108 for(int i=0; i<3; ++i){ 109 for(int j=0; j<3; ++j){ 110 cin>>c; 111 if(c=='x') 112 eight[i][j]=0, xx = i, xy = j; 113 else 114 eight[i][j]= c-'0'; 115 } 116 } 117 tar=8; 118 for(int i=7; i>0; --i) 119 tar<<=4, tar |= i; 120 int cnt=0; 121 for(int i=0; i<9; ++i){ 122 for(int pi=0; pi<i; ++pi) 123 if(eight[pi/3][pi%3] && eight[pi/3][pi%3]<eight[i/3][i%3]) 124 cnt++; 125 } 126 if(cnt%2) 127 printf("unsolvable\n"); 128 else 129 astar(); 130 return 0; 131 }
另外八数码问题的三种实现(bfs,dbfs,a*):