最短路径 A*算法 应用堆优化
来源:互联网 发布:java ajax文件上传 编辑:程序博客网 时间:2024/06/05 23:53
!!(5月27日)发现一个很牛的东东,可以加深理解A* http://qiao.github.io/PathFinding.js/visual/
去年的这个时候和同学一起玩code vs asia的比赛学会了A*算法
当初在数据结构算法什么都不懂的情况下,我们能写出A*算法已经感觉非常满足了
当初用java进行实现的,那个时候脑袋里就只想着能实现就好,于是那个神奇的A*就被我们迷迷糊糊的写出来了
下面就想着高兴呢,也没仔细想过整体的流程,那里可以有优化的地方。虽然整体实现了,但是细节方面简直是令人发指
时隔一年,玩acm再次碰到了那个相似的使用A*算法的情况。于是凭借着我寥寥无几的数据结构知识外加蹩脚的c,c++语言使用
写出了一个自我感觉比以前java实现的优化了那么一点点的A*算法
接下来正题:
如果你清楚A*算法但是不知道怎么实现,我这里可能稍微给你一点帮助
如果你不清楚A*算法,可以先去学一下,网络上有很多比较好的文章,这里我就不多做讲解了
A*堆优化方式:A*算法利用了一个估价函数,计算图上节点的时候,对节点进行了整体的估价
然后选出最优的节点进行访问,以此类推...
既然是选择最优的节点,那么我们就可以实现一个优先队列。来方便我们取出最优的节点。所以使用堆就成了我们优化的不二选择
把能访问的节点加入我们的开放队列(堆形式),取出F最小的节点,然后访问与这个节点相连的节点,并且把满足条件能访问的加入
开放列表,如果满足条件并且已经加入到开放列表中了,那么就比较其G值。选取比较小的,然后更新开放列表中的节点。
(这里,在使用以维护F的最小值为条件的堆中,我们无法快速判断一个节点是否已经存在于堆中。所以我想到了另外再构建一个hash图
维护原图的每一个节点在堆中的位置,这样就能使用hash图直接的判断原图中的节点是否已经存在于堆中。维护hash图,需要和维护堆进行同步
所以每次加入一个节点时维护hash图的复杂度为logN,同维护堆的logN,并且在判断的时候是O(1)的时间复杂度,但构建hash图又增加了空间复杂度)
(优化好处,比A*算法使用普通链表形式进行维护的开放列表时间复杂度上好很多,普通链表取最小值,打擂台形式,时间复杂度O(N),插入的时候
判断有没有已经被插入也是O(N),所以比较时间复杂度优点显而易见)
下面是我憋脚的实现。
测试的图为二维的平面图,可以上下左右,四个方向行走,也可以八个方向行走(八个方向少考虑一个问题),图上0表示可以走,1表示不通。
八方向少考虑的问题是:如果图为00 那么我能否从(1,1)直接走到(2,2)也就是斜角过能否“蹩马脚”
10
额,打字好累直接贴代码好了
#include<stdio.h>#include<stdlib.h>#define MAX 500static int DX[8]= {-1,0,1,0,1,-1,1,-1};static int DY[8]= {0,1,0,-1,1,1,-1,-1};int grap[MAX][MAX];int hash[MAX][MAX];int n,m;struct Node { int x,y,g,h,f;};Node heap[MAX*MAX];int h_end=0;int insert(Node n);//堆中插入节点int update(int idx,Node n);//向上更新堆中的节点Node getMin();//取出堆中的最小值void swap(int idx1,int idx2);//交换hash数组对应堆中节点的位置,并交换堆中的节点void add_open(int x,int y,int g,Node e,int dir);//把图上的节点添加进开放列表void add_close(Node n);//把图上的节点添加进关闭列表void aStar(Node s,Node e,int dir);//主要算法int insert(Node n) { return update(++h_end,n);}int update(int idx,Node n) { int e=idx,p; heap[e]=n; while(e>1) { p=e>>1; if(heap[e].f<heap[p].f) { swap(e,p); e=p; } else break; } return e;}Node getMin() { int ls,rs,rt=1; Node res=heap[rt]; heap[rt]=heap[h_end--]; while(1) { ls=rt<<1; rs=rt<<1|1; if(ls>h_end||rs>h_end) { if(ls<=h_end&&heap[rt].f>heap[ls].f)swap(rt,ls); break; } if(heap[rt].f<=heap[ls].f&&heap[rt].f<=heap[rs].f)break; if(heap[rt].f>heap[ls].f&&heap[rs].f>=heap[ls].f) { swap(rt,ls); rt=ls; } else { swap(rt,rs); rt=rs; } } return res;}void swap(int idx1,int idx2) { hash[heap[idx1].x][heap[idx1].y]=idx2; hash[heap[idx2].x][heap[idx2].y]=idx1; Node tmp=heap[idx1]; heap[idx1]=heap[idx2]; heap[idx2]=tmp;}void add_open(int x,int y,int g,Node e,int dir) { if(x<0||x>=n)return; if(y<0||y>=m)return; if(grap[x][y]!=0||hash[x][y]==-1)return; Node tmp; tmp.x=x;tmp.y=y; int h; if(dir<4) { g=g+10; h=(abs(e.x-x)+abs(e.y-y))*10; } else { g=g+14; h=(abs(e.x-x)+abs(e.y-y))*10; } tmp.g=g; tmp.h=h; tmp.f=g+h; if(hash[x][y]!=0) { if(heap[hash[x][y]].g>g) { update(hash[x][y],tmp); } } else { hash[x][y]=insert(tmp); }}void add_close(Node n) { hash[n.x][n.y]=0; grap[n.x][n.y]=88;}void aStar(Node s,Node e,int dir) { hash[s.x][s.y]=insert(s); Node tmp; int x,y,g,i; while(h_end>0) { tmp=getMin(); add_close(tmp); if(tmp.x==e.x&&tmp.y==e.y) { printf("%d\n",tmp.g); break; } for(i=0; i<dir; i++) { x=tmp.x+DX[i]; y=tmp.y+DY[i]; g=tmp.g; add_open(x,y,g,e,i); } }}int main() { freopen("nput.txt","r",stdin); int x1,y1,x2,y2,i,j; scanf("%d%d",&n,&m); for(i=0; i<n; i++) { for(j=0; j<m; j++) { scanf("%d",&grap[i][j]); } } scanf("%d%d%d%d",&x1,&y1,&x2,&y2); Node star,end; star.x=x1-1;star.y=y1-1;star.g=0; end.x=x2-1;end.y=y2-1;end.g=0; aStar(star,end,4); for(i=0; i<n; i++) { for(j=0; j<m; j++) { printf("%2d ",grap[i][j]); } printf("\n"); } return 0;}
- 最短路径 A*算法 应用堆优化
- A*最短路径算法
- Dijsktra 最短路径和堆算法
- Astar A*算法 最短路径算法
- 最短路径+堆
- Dijkstra最短路径算法的优化
- 深入A*算法----浅析A*算法在搜索最短路径中的应用
- 深入A*算法----浅析A*算法在搜索最短路径中的应用
- A* 算法求解最短路径
- A* 算法求解最短路径
- A*算法的最短路径实现!
- A* 算法搜索最短路径
- A*算法求解最短路径
- A* 算法搜索最短路径
- 最短路径算法Dijkstra和A*
- A星算法,找寻最短路径
- 最短路径算法及应用
- 最短路径算法及应用
- servlet详解
- DDR学习笔记
- ftp运用
- poj 2007 Scrambled Polygon(凸多边形顶点输出)
- 使用Maven构建Android项目
- 最短路径 A*算法 应用堆优化
- c#设计模式之工厂模式
- Java注解(自定义方法注解使用及测试)
- ADO.net中的五个主要对象
- linux kernel data struct : find longest sub string
- 孙鑫 MFC 20130511
- android 进程退出方式(非activity消亡)
- linux ipv4 keep alive
- 下载android的linux内核的方法