A*,八数码

主要搜索过程:
创建两个表,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 
#include 
#include 
#include 
using namespace std;
struct node
{string a;//nameint d;//depth,and the g()'s valueint z;//0's weizhiint p;//priority,the f()'s valuefriend 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 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;
} 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部