A*,八數位

來源:互聯網
上載者:User

主要搜尋過程:
建立兩個表,OPEN表儲存所有已產生而未考察的節點,CLOSED表中記錄已訪問過的節點。
遍曆當前節點的各個節點,將n節點放入CLOSE中,取n節點的子節點X,->算X的估價值->

While(OPEN!=NULL)
{

從OPEN表中取估價值f最小的節點n;

if(n節點 in CLOSE) continue;

if(X節點==目標節點)break;//全部子節點
else
{
if(X in OPEN) 比較兩個X的估價值f//注意是同一個節點的兩個不同路徑的估價值
  if( X的估價值小於OPEN表的估價值 )
   更新OPEN表中的估價值; //取最小路徑的估價值??

if(X in CLOSE) 比較兩個X的估價值//注意是同一個節點的兩個不同路徑的估價值
  if( X的估價值小於CLOSE表的估價值 )
   把X從CLOSE列表中移除; 把X節點放入OPEN //取最小路徑的估價值

if(X not in both)
求X的估價值;
   並將X插入OPEN表中; //還沒有排序

}

將n節點插入CLOSE表中;
按照估價值將OPEN表中的節點排序; //實際上是比較OPEN表內節點f的大小,從最小路徑的節點向下進行。

}

/*

通過幾天的學習啟發學習法搜尋以及解決相應的一個演算法題,對搜尋演算法有了進一步的認識.

感謝這些部落客人的翻譯:

http://blog.vckbase.com/panic/archive/2005/03/20/3778.aspx

http://blog.vckbase.com/panic/archive/2005/03/28/4144.html

http://www.5igis.com/algorithm/shortpath.htm

http://hi.baidu.com/sonwkuni/blog/item/8be877af32b069cb7dd92a30.html

*/

//我用了stl的優先隊列,而且,沒有實現去更新open表中的已有的值,我只是用一個新的節點加到open表中

//當然你可以運用自己寫的最小堆來維護這個值,有興趣的可以參考這裡:點擊開啟連結

#include <queue>#include <string>#include <algorithm>#include <cstdio>using namespace std;struct node{  string a;//name  int d;//depth,and the g()'s value  int z;//0's weizhi  int p;//priority,the f()'s value  friend bool operator < (const node & n1, const node & n2)//p值越小優先順序越高   {        return n1.p > n2.p;  }  node():d(0),z(0),p(999999999){}};node temp;node now;string start("123456780");//初始化狀態 string end("123456780");//最後狀態 int fac[10] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};int hash[362881][2];//hash表 :[][0] = 等於0說明還沒進過open表,大於0代表已經在open列表中了,而且其值就是f值                    //         [][1] = 大於0代表已經在close列表中了,而且其值就是f值                    int dir[9][4] = {           //0所在位置與交換後可以到達的位置,9表示不能移動到的位置                   {1,3,9,9},//0                  {0,2,4,9},//1                  {1,5,9,9},//2                  {0,4,6,9},//3                  {1,3,5,7},//4                  {2,4,8,9},//5                  {3,7,9,9},//6                  {4,6,8,9},//7                  {5,7,9,9},//8                };int xy[9][2] = {//為每個位置設立座標                  {1,1},//0                 {1,2},//1                 {1,3},//2                 {2,1},//3                 {2,2},//4                 {2,3},//5                 {3,1},//6                 {3,2},//7                 {3,3},//8                };                  priority_queue<node> q;void init(){  for(int i = 0; i < 9; ++i)   scanf("%s",&end[i]);}int hashindex()//排列與hash {    int result = 0;    string tt = temp.a;    for(int j =1; j < 9; ++j)//從第二個數開始     {        int count = 0;//逆序的個數         for(int k = 0;k < j; ++k) //如果前面的大於後面的則逆序個數+1         {                        if(tt[j] < tt[k]) ++count;        }        result += count*fac[j];//1-9的階層     }    return result;}int h()//曼哈頓距離 {   string a = end;   string b = temp.a;   int ans = 0;   for(int i = 0; i < 9; ++i)   {      if(b[i] == '0') continue;      for(int j = 0; j < 9; ++j)      {        if(b[i] == a[j])        {          int xx = xy[i][0]-xy[j][0];          if(xx < 0) xx = -xx;//|x1-x2|          int yy = xy[i][1]-xy[j][1];          if(yy < 0) yy = -yy;//|y1-y2|          ans += (xx +yy);// |x1-x2|+|y1-y2|          break;        }      }   }   return ans;}bool bfs(int zz,int xx)//0的位置,被交換的方位 {  temp = now;  temp.a[zz] = temp.a[xx];  temp.a[xx] = '0';  if(temp.a == end)//找到目標節點就返回true    return true;  int isok = hashindex();  temp.d += 1;  temp.z = xx;  temp.p = temp.d+h();    if(hash[isok][1] > 0 && hash[isok][1] > temp.p)//假如已經在close列表中了,而且現在的F值比原來的小   {                                              //說明有更好的路徑,因為他們的h值都相同.     hash[isok][1] = 0;//從close表中出去     q.push(temp);    return false;  }    if(hash[isok][0] == 0 || hash[isok][0] > temp.p)//還沒在open表中,或者已經在open表中了但是現在的F值比原來的小   {    hash[isok][0] = temp.p;//進入open表或者更新open表中原有的節點的值     q.push(temp);    return false;  }}int A_star(){  int ans = 0;  temp.a = start;  temp.d = 0;  temp.z = 8;  hash[hashindex()][0] = 0;//起始狀態   temp.p = 0;  q.push(temp);  while(!q.empty())  {    now = q.top();    q.pop();    temp = now;    int nowhashindex = hashindex();    if(hash[nowhashindex][1] > 0) continue;//如果已經在close表中了就跳過     for(int i = 0; i < 4; ++i)    {      if(dir[now.z][i] < 9 && bfs(now.z,dir[now.z][i]))//如果可以被擴充       {        ans = now.d+1;        return ans;      }    }    hash[nowhashindex][1] = now.p;//進close表   }}int main(){  init();  printf("%d\n",A_star());  return 0;} 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.