算法起步之A星算法
原文:算法起步之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星算法的更多相关文章
- POJ 2449 Remmarguts' Date (SPFA + A星算法) - from lanshui_Yang
题目大意:给你一个有向图,并给你三个数s.t 和 k ,让你求从点 s 到 点 t 的第 k 短的路径.如果第 k 短路不存在,则输出“-1” ,否则,输出第 k 短路的长度. 解题思路:这道题是一道 ...
- 算法起步之动态规划LCS
原文:算法起步之动态规划LCS 前一篇文章我们了解了什么是动态规划问题,这里我们再来看动态规划另一个经典问题,最长公共子序列问题(LCS),什么是子序列,我们定义:一个给定序列将其中的0个或者多个元素 ...
- 算法起步之Kruskal算法
原文:算法起步之Kruskal算法 说完并查集我们接着再来看这个算法,趁热打铁嘛.什么是最小生成树呢,很形象的一个形容就是铺自来水管道,一个村庄有很多的农舍,其实这个村庄我们可以看成一个图,而农舍就是 ...
- 算法起步之Prim算法
原文:算法起步之Prim算法 prim算法是另一种最小生成树算法.他的安全边选择策略跟kruskal略微不同,这点我们可以通过一张图先来了解一下. prim算法的安全边是从与当前生成树相连接的边中选择 ...
- 算法起步之Bellman-Ford算法
原文:算法起步之Bellman-Ford算法 从这篇开始我们开始介绍单源最短路径算法,他是图算法之一,我们前面说的贪心,图的遍历,动态规划都是他的基础,单源最短路径其实说的就是图中节点到节点的最短路径 ...
- 算法起步之Dijkstra算法
原文:算法起步之Dijkstra算法 友情提示:转载请注明出处[作者 idlear 博客:http://blog.csdn.net/idlear/article/details/19687579 ...
- Cocos2d-x 3.1.1 学习日志16--A星算法(A*搜索算法)学问
A *搜索算法称为A星算法.这是一个在图形平面,路径.求出最低通过成本的算法. 经常使用于游戏中的NPC的移动计算,或线上游戏的BOT的移动计算上. 首先:1.在Map地图中任取2个点,開始点和结束点 ...
- A*搜寻算法(A星算法)
A*搜寻算法[编辑] 维基百科,自由的百科全书 本条目需要补充更多来源.(2015年6月30日) 请协助添加多方面可靠来源以改善这篇条目,无法查证的内容可能会被提出异议而移除. A*搜索算法,俗称A星 ...
- 算法生成N芒星
前面两个图像生成算法是:道教的太极八卦图和佛教的卐和卍字图.这一节整个洋气的图像:芒星.但愿我别召唤出什么恐怖的禁忌,尤其今晚还是万圣节之夜.平时看玄幻小说,经常读到有关六芒星,七芒星,九芒星的技法. ...
随机推荐
- 【linux kernel】 中断处理-中断下半部
欢迎转载,转载时需保留作者信息,谢谢. 邮箱:tangzhongp@163.com 博客园地址:http://www.cnblogs.com/embedded-tzp Csdn博客地址:http:// ...
- javascript笔记整理(变量作用域)
变量的作用域(作用域:指的就是一段代码的作用范围) 一.变量的作用域 1.全局变量(在代码中任何地方都能够访问得到的变量,拥有全局的作用域) A.最外层函数外面定义的变量 var a=1; funct ...
- delphi模态窗体最小化会隐藏的问题
在使用delphi创建模态窗体的时候最小化窗体会导致最小化的窗体不可见,再次点击主窗体才会显示. 在这个模态窗体中增加以下函数 procedure WmSysCommand(var msg: TMes ...
- 11.ThinkPHP 3.1.2 连贯操作
==================================================== 一.常用连贯操作 1.where 帮助我们设置查询条件 2.order 对结果进行排序 $ar ...
- windows/linuxjdk安装,jdk1.6升级到1.7
一.JDK: JAVA_HOME: C:\Program Files\Java\jdk1.7.0_79 PATH: ;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin CLASS ...
- 基于visual Studio2013解决C语言竞赛题之1021九九乘法表
题目 解决代码及点评 /* 功能:请编程序按如下格式打印一个直角三角形的九九乘法表: 1 2 3 4 5 6 7 8 9 4 6 8 10 12 14 16 18 9 1 ...
- HDU - 5036 Explosion
Problem Description Everyone knows Matt enjoys playing games very much. Now, he is playing such a ga ...
- android Activity之间数据传递 Parcelable和Serializable接口的使用
Activity之间传数据时,为了避免麻烦,往往会将一些值封装成对象,然后将整个对象传递过去.传对象的时候有两种情况,一种是实现Parcelable接口,一种是实现Serializable接口.0.解 ...
- 在jsp页面下, 让eclipse完全支持HTML/JS/CSS智能提示(转)
我们平时用eclipse开发jsp页面时智能提示效果不太理想,今天用了两个小时发现了eclipse也可以像Visual Studio 2008那样完全智能提示HTML/JS/CSS代码,使用ecl ...
- Android手势识别(单击 双击 抬起 短按 长按 滚动 滑动)
对于触摸屏,其原生的消息无非按下.抬起.移动这几种,我们只需要简单重载onTouch或者设置触摸侦听器setOnTouchListener即可进行处理.不过,为了提高我们的APP的用户体验,有时候我们 ...