A*,八数码
来源:互联网 发布:淘宝卖家怎么看客流量 编辑:程序博客网 时间:2024/05/19 19:43
主要搜索过程:
创建两个表,OPEN表保存所有已生成而未考察的节点,CLOSED表中记录已访问过的节点。
遍历当前节点的各个节点,将n节点放入CLOSE中,取n节点的子节点X,->算X的估价值->
{
从OPEN表中取估价值f最小的节点n;
if(n节点 in CLOSE) continue;
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表中; //还没有排序
}
按照估价值将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;}
- 八数码A*搜索
- A*,八数码
- A星八数码
- hdu1043【八数码】【A*】
- 八数码 A*算法
- a*八数码(有问题)
- 八数码(A* 735ms)
- 八数码(A星)
- 八数码游戏 A*算法
- 八数码问题A*算法
- hdu 1043 八数码 A*
- 八数码问题-A*算法
- poj-1077 八数码 【a*】
- 八数码之A*解决方法
- 八数码问题--A*算法
- A*搜索 - 八数码问题
- 八数码难题 codevs1225 a*
- 八数码问题——A*搜索
- ABAP读取文件
- Direct3D轮回:游戏场景之河流
- Linux 的多线程编程的高效开发经验
- jdbc中的batch
- 通用Makefile
- A*,八数码
- map
- 我对单源最短路径的思考
- 源码网站1
- jfreechar
- ,string.Empty和null三者的
- 下雨
- fprintf、printf、sprintf、fscanf、scanf、sscanf详细分析
- 制作更酷的JList界面