原文:算法起步之A星算法

用途:

寻找最短路径,优于bfs跟dfs

描述:

基本描述是,在深度优先搜索的基础上,增加了一个启发式算法,在选择节点的过程中,不是盲目选择,而是有目的的选的,F=G+H,f(n)=g(n)+h(n)

g(n)是当前节点到开始节点的花费h(n)是当前节点到结束节点的花费f(n)是衡量一个衡量标准

最核心的是h(n)的估算,这里用到了启发式算法,且h(n)=<h*(n) (h*(n)为实际问题的代价值)。曼哈顿(manhattan)估价函数曼哈顿方法,它计算从当前格到目的格之间水平和垂直的方格的数量总和,忽略对角线方向,然后把结果乘以10。在选择节点时,根据节点的f(n)的大小进行选择,总是选择最小的。这样会有两个队列,一个open队列用来存储所预备选择节点,close队列用来存储已经走过的节点,open队列是一个优先队列,每次从open队列中取f值最小的节点,检查后将节点放到close里。并把关联节点放到open队列中,这样一直循环到终点节点加入到open列表中时。

资料:

http://www.java3z.com/cwbwebhome/article/article2/2825.html的flash做的很形象

http://www.cppblog.com/mythit/archive/2009/04/19/80492.aspx讲的很详细

http://developer.51cto.com/art/201112/307973.htmjava版代码

代码:

package com.langsin.gsc.acm.astar;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* A*寻路算法
* 地图中1表示可以通过,0表示不能通过
* 当结束点加到open队列中时查找结束
* gh值的设定问题。
*/
public classAstar {
// 地图
private int[][] map;
// 行
private int row;
// 列
private int colum;
// 水平或竖直方向的花费
private int COST_ZHI=10;
// 对角线方向的花费
private int COSR_XIE=14;
// open列表
private List<Node> open;
// close列表
private List<Node> close;
// 开始节点
private Node beginNode;
// 结束节点
private Node endNode;
// 结构节点
private Node resultNode=null;
/**
* 测试方法
* @param args
*/
public static void main(String[] args) {
int[][] map = new int[][] {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{1, 1, 1, 1, 0, 1, 1, 1, 1, 1 },
{1, 1, 1, 1, 0, 1, 1, 1, 1, 1 },
{1, 1, 1, 1, 0, 1, 1, 1, 1, 1 },
{1, 1, 1, 1, 0, 1, 1, 1, 1, 1 },
{1, 1, 1, 1, 0, 1, 1, 1, 1, 1 }
};
Astarastar=newAstar(map, 6, 10);
astar.search(0,0, 5, 9);
Noderesult=astar.getResultNode();
while(result.getParentnode()!=null){
map[result.getX()][result.getY()]=2;
result=result.getParentnode();
}
map[result.getX()][result.getY()]=2; for (int i = 0; i <6; i++) {
for (int j = 0; j < 10; j++){
System.out.print(" "+map[i][j]);
}
System.out.println();
}
}
/**
* 初始化地图长宽还有open跟close队列
* @param map
* @param row
* @param colum
*/
public Astar(int[][] map,int row,int colum){
this.map=map;
this.row=row;
this.colum=colum;
open=newArrayList<Node>();
close=newArrayList<Node>();
}
/**
* 开始节点的坐标跟终点节点的坐标
* @param x1
* @param y1
* @param x2
* @param y2
*/
public void search(int x1,int y1,int x2,int y2) {
// 如果在节点外直接返回
if (x1<0||x1>=row||y1<0||y1>colum||x2<0||x2>=row||y2<0||y2>colum) {
return;
}
// 如果无法通过直接返回
if (map[x1][y1]==0||map[x2][y2]==0) {
return;
}
beginNode=new Node(x1, y1, null);
endNode=new Node(x2, y2, null);
// 开始按方向搜索
searchnode(beginNode, endNode);
}
/**
* 分八个方向开始检查结点
* @param bNode
* @param eNode
*/
private void searchnode(NodebNode,Node eNode){
// 将开始节点加入到open中
open.add(bNode);
// 当open列表中有节点时就循环
while (open.size()>0) {
// 取出第一个节点设置成当前节点开始检查他的八个方向
Nodenownode=open.get(0);
// 如果是终点则推出循环
if (nownode.getX()==endNode.getX()&&nownode.getY()==endNode.getY()) {
// 将这个节点设置成结果节点
resultNode=nownode;
break;
}
// 向上
if(nownode.getX()-1>=0) {
checkNode(nownode.getX()-1,nownode.getY(), nownode,COST_ZHI);
}
// 向下
if (nownode.getX()+1<row) {
checkNode(nownode.getX()+1,nownode.getY(), nownode, COST_ZHI);
}
// 向左
if(nownode.getY()-1>=0) {
checkNode(nownode.getX(),nownode.getY()-1, nownode, COST_ZHI);
}
// 向右
if (nownode.getY()+1<colum) {
checkNode(nownode.getX(), nownode.getY()+1,nownode, COST_ZHI);
}
// 左上
if(nownode.getX()-1>=0&&nownode.getY()-1>=0) {
checkNode(nownode.getX()-1,nownode.getY()-1, nownode, COSR_XIE);
}
// 右上
if(nownode.getX()-1>=0&&nownode.getY()+1<colum) {
checkNode(nownode.getX()-1,nownode.getY()+1, nownode, COSR_XIE);
}
// 左下
if (nownode.getX()+1<row&&nownode.getY()-1>=0){
checkNode(nownode.getX()+1,nownode.getY()-1, nownode, COSR_XIE);
}
// 右下
if (nownode.getX()+1<row&&nownode.getY()+1<colum) {
checkNode(nownode.getX()+1,nownode.getY()+1, nownode, COSR_XIE);
}
// 将open列表中的第一个取出放入到close列表中
close.add(open.remove(0));
// 对open列表进行排序
Collections.sort(open, new nodecompare());
} }
/**
* 检查每一个结点
* @param x
* @param y
* @param parentNode
* @param cost
*/
private void checkNode(int x,int y,Node parentNode,int cost){
// 如果无法通过则返回
if (map[x][y]==0) {
return ;
}
// 如果在close中有则返回
if (checklist(close, x, y)!=-1) {
return;
}
// 建立这个结点
Nodenode=newNode(x, y, parentNode);
// 计算他的fgh值
setFGH(node,cost, endNode);
int index=-1;
// 如果open中有,若f值小则更新他否则不添加.没有的话则添加这个结点
if ((index=checklist(open, x, y))!=-1) {
if (node.getF()<open.get(index).getF()) {
open.set(index, node);
}
}else {
open.add(node);
}
} /**
* 计算FGH值
* @param node
*/
private void setFGH(Node node,int cost,Node eNode){ if (node.getParentnode()!=null) {
node.setG(node.getParentnode().getG()+cost);
}else {
node.setG(cost);
}
// H值的一种计算方法,也可以采用其他方法 曼哈顿(manhattan)估价函数
node.setH((Math.abs(node.getX()-eNode.getX())+Math.abs(node.getY()-eNode.getY()))*10);
node.setF(node.getG()+node.getH()); }
/**
* 检查列表中是否已经有该结点
* @param list
* @param x
* @param y
* @return
*/
private intchecklist(List<Node> list,int x,inty){
int key=-1;
for (int i = 0; i <list.size(); i++) {
if(list.get(i).getX()==x&&list.get(i).getY()==y) {
key=i;
break;
}
}
return key;
}
/**
* 放回结果路径(链表)
* @return
*/
public Node getResultNode(){
return resultNode;
}
} /**
* 节点类。主要包括xy坐标父节点 f=g+h
*
*/
class Node{
// 坐标xy
private int x;
private int y;
// 父节点
private Node parentnode;
// F=G+H
private int g;
private int h;
private int f;
// 构造函数
public Node(int x, int y, Node parentnode) {
super();
this.x = x;
this.y = y;
this.parentnode = parentnode;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public Node getParentnode() {
return parentnode;
}
public void setParentnode(Nodeparentnode) {
this.parentnode = parentnode;
}
public int getG() {
return g;
}
public void setG(int g) {
this.g = g;
}
public int getH() {
return h;
}
public void setH(int h) {
this.h = h;
}
public int getF() {
return f;
}
public void setF(int f) {
this.f = f;
}
}
/**
* 比较器用来给open队列排序
*/
class nodecompare implements Comparator<Node>{
@Override
public int compare(Node o1, Nodeo2) {
return o1.getF()-o2.getF();
}
}

算法起步之A星算法的更多相关文章

  1. POJ 2449 Remmarguts' Date (SPFA + A星算法) - from lanshui_Yang

    题目大意:给你一个有向图,并给你三个数s.t 和 k ,让你求从点 s 到 点 t 的第 k 短的路径.如果第 k 短路不存在,则输出“-1” ,否则,输出第 k 短路的长度. 解题思路:这道题是一道 ...

  2. 算法起步之动态规划LCS

    原文:算法起步之动态规划LCS 前一篇文章我们了解了什么是动态规划问题,这里我们再来看动态规划另一个经典问题,最长公共子序列问题(LCS),什么是子序列,我们定义:一个给定序列将其中的0个或者多个元素 ...

  3. 算法起步之Kruskal算法

    原文:算法起步之Kruskal算法 说完并查集我们接着再来看这个算法,趁热打铁嘛.什么是最小生成树呢,很形象的一个形容就是铺自来水管道,一个村庄有很多的农舍,其实这个村庄我们可以看成一个图,而农舍就是 ...

  4. 算法起步之Prim算法

    原文:算法起步之Prim算法 prim算法是另一种最小生成树算法.他的安全边选择策略跟kruskal略微不同,这点我们可以通过一张图先来了解一下. prim算法的安全边是从与当前生成树相连接的边中选择 ...

  5. 算法起步之Bellman-Ford算法

    原文:算法起步之Bellman-Ford算法 从这篇开始我们开始介绍单源最短路径算法,他是图算法之一,我们前面说的贪心,图的遍历,动态规划都是他的基础,单源最短路径其实说的就是图中节点到节点的最短路径 ...

  6. 算法起步之Dijkstra算法

    原文:算法起步之Dijkstra算法 友情提示:转载请注明出处[作者 idlear    博客:http://blog.csdn.net/idlear/article/details/19687579 ...

  7. Cocos2d-x 3.1.1 学习日志16--A星算法(A*搜索算法)学问

    A *搜索算法称为A星算法.这是一个在图形平面,路径.求出最低通过成本的算法. 经常使用于游戏中的NPC的移动计算,或线上游戏的BOT的移动计算上. 首先:1.在Map地图中任取2个点,開始点和结束点 ...

  8. A*搜寻算法(A星算法)

    A*搜寻算法[编辑] 维基百科,自由的百科全书 本条目需要补充更多来源.(2015年6月30日) 请协助添加多方面可靠来源以改善这篇条目,无法查证的内容可能会被提出异议而移除. A*搜索算法,俗称A星 ...

  9. 算法生成N芒星

    前面两个图像生成算法是:道教的太极八卦图和佛教的卐和卍字图.这一节整个洋气的图像:芒星.但愿我别召唤出什么恐怖的禁忌,尤其今晚还是万圣节之夜.平时看玄幻小说,经常读到有关六芒星,七芒星,九芒星的技法. ...

随机推荐

  1. c语言:链表排序, 链表反转

    下面将实现链表排序的排序和遍历显示功能: 所定义的链表结构如下: head -> p1 -> p2 ->p3 ->....->pn; head的本身不作为数据节点,hea ...

  2. TPersistent的三个用途(读写DFM文件,Assign,RTTI),最主要还是第三个用途

    不是什么类对象都需要RTTI,如果把它放在TObject,除了增加可执行文件的大小以及运行内存空间以外,没什么好处.

  3. 面试中关于Java中涉及到知识点(转)

    本篇文章会对面试中常遇到的Java技术点进行全面深入的总结,帮助我们在面试中更加得心应手,不参加面试的同学也能够借此机会梳理一下自己的知识体系,进行查漏补缺. 1. Java中的原始数据类型都有哪些, ...

  4. encode_json 会对给定的Perl的数据结构转换为一个UTF-8 encoded, binary string.

    use JSON qw/encode_json decode_json/ ; use Encode; my $data = [ { 'name' => 'Ken' , 'age' => 1 ...

  5. 一则 ORA-00471 处理方法

    公司新上架一台服务到机房,硬件是IBM X3850 X5,硬件配置算是好的,内存有128GB.SA安装好系统--(版本sule 32bit)后通知我可以安装数据库了.忙活半天,安装好oracle 92 ...

  6. Qt 中文乱码解决大全

    源地址:http://blog.csdn.net/xcy2011sky/article/details/7168376 解决中文乱码,最好知道乱码是什么格式比如说:utf-8. 解决方案: 1.让整个 ...

  7. UVA - 12119 The Bells are Ringing (枚举)

    Perhaps you all have heard the mythical story about Tower of Hanoi (The details of this story is not ...

  8. 基于visual Studio2013解决面试题之0201二叉树转链表

     题目

  9. VS2010 编译安装boost库

    实践是最好的办法..学习C++,想试试线程,然后打算用boost库,结果boost库编译差点吓到我..没看到比较完整的安装教程..一直耽搁.今天动手.完成了.方法记录如下:1.下载boost从boos ...

  10. 设置静态IP

    设定IP $sudo vi/etc/network/interfaces autolo iface lo inet loopback 加入下面内容 autoeth0 iface eth0inet st ...