最近开始接触寻路算法,对此不太了解的话建议读者先看这篇文章 《如何快速找到最优路线?深入理解游戏中寻路算法》 。

所有寻路算法都需要一种方法以数学的方式估算某个节点是否应该被选择。大多数游戏都会使用 启发式 (heuristic) ,以 h(x) 表示,就是估算从某个位置到目标位置的开销。理想情况下,启发式结果越接近真实越好。

——《游戏编程算法与技巧》

今天主要说的是贪婪最佳优先搜索(Greedy Best-First Search),贪心算法的含义是:求解问题时,总是做出在当前来说最好的选择。通俗点说就是,这是一个“短视”的算法。

`

为什么说是“短视”呢?首先要明白一个概念: 曼哈顿距离 。

曼哈顿距离

曼哈顿距离被认为不能沿着对角线移动,如下图中,红、蓝、黄线都代表等距离的曼哈顿距离。绿线代表 欧氏距离 ,如果地图允许对角线移动的话,曼哈顿距离会经常比欧式距离高。

在 2D 地图中,曼哈顿距离的计算如下:

贪婪最佳优先搜索的简介

贪婪最佳优先搜索的每一步,都会查找相邻的节点,计算它们距离终点的曼哈顿距离,即最低开销的启发式。

贪婪最佳优先搜索在障碍物少的时候足够的快,但最佳优先搜索得到的都是次优的路径。例如下图,算法不断地寻找当前 h(启发式)最小的值,但这条路径很明显不是最优的。

贪婪最佳优先搜索“未能远谋”,大多数游戏都要比贪婪最佳优先算法所能提供的更好的寻路,但大多数寻路算法都是基于贪婪算法,所以了解该算法很有必要。

首先是节点类,每个节点需要存储上一个节点的引用和 h 值,其他信息是为了方便算法的实现。存储上一个节点的引用是为了像一个链表一样,最后能通过引用得到路径中所有的节点。

public class Node

{

// 上一个节点

public Node parent;

// 节点的 h(x) 值

public float h;

// 与当前节点相邻的节点

public List adjecent = new List();

// 节点所在的行

public int row;

// 节点所在的列

public int col;

// 清除节点信息

public void Clear()

{

parent = null;

h = 0.0f;

}

}

下面是图类,图类最主要的任务就是根据提供的二维数组初始化所有的节点,包括寻找他们的相邻节点。

// 图类

public class Graph

{

public int rows = 0;

public int cols = 0;

public Node[] nodes;

public Graph(int[, ] grid)

{

rows = grid.GetLength(0);

cols = grid.GetLength(1);

nodes = new Node[grid.Length];

for (int i = 0; i < nodes.Length; i++)

{

Node node = new Node();

node.row = i / cols;

node.col = i - (node.row * cols);

nodes[i] = node;

}

// 找到每一个节点的相邻节点

foreach (Node node in nodes)

{

int row = node.row;

int col = node.col;

// 墙,即节点不能通过的格子

// 1 为墙,0 为可通过的格子

if (grid[row, col] != 1)

{

// 上方的节点

if (row > 0 && grid[row - 1, col] != 1)

{

node.adjecent.Add(nodes[cols * (row - 1) + col]);

}

// 右边的节点

if (col < cols - 1 && grid[row, col + 1] != 1)

{

node.adjecent.Add(nodes[cols * row + col + 1]);

}

// 下方的节点

if (row < rows - 1 && grid[row + 1, col] != 1)

{

node.adjecent.Add(nodes[cols * (row + 1) + col]);

}

// 左边的节点

if (col > 0 && grid[row, col - 1] != 1)

{

node.adjecent.Add(nodes[cols * row + col - 1]);

}

}

}

}

}

在算法类中,我们需要记录开放集合和封闭集合。开放集合指的是当前步骤我们需要考虑的节点,例如算法开始时就要考虑初始节点的相邻节点,并从其找到最低的 h(x) 值开销的节点。封闭集合存放已经计算过的节点。

// 开放集合

public List reachable;

// 封闭集合,存放已经被算法估值的节点

public List explored;

下面是算法主要的逻辑,额外的函数可以查看项目源码。

public Stack Finding()

{

// 存放查找路径的栈

Stack path;

Node currentNode = reachable[0];

// 迭代查找,直至找到终点节点

while (currentNode != destination)

{

explored.Add(currentNode);

reachable.Remove(currentNode);

// 将当前节点的相邻节点加入开放集合

AddAjacent(currentNode);

// 查找了相邻节点后依然没有可以考虑的节点,查找失败。

if (reachable.Count == 0)

{

return null;

}

// 将开放集合中h值最小的节点当做当前节点

currentNode = FindLowestH();

}

// 查找成功,则根据节点parent找到查找到的路径

path = new Stack();

Node node = destination;

// 先将终点压入栈,再迭代地把node的前一个节点压入栈

path.Push(node);

while (node.parent != null)

{

path.Push(node.parent);

node = node.parent;

}

return path;

}

除此以外还有些展示算法的类,代码不在这里展出。下面是算法执行的截图,其中白色格子为可走的格子,灰色格子是不可穿越的,红色格子为查找到的路径,左上角格子为查找起点,右上角格子为查找终点。

后一个实例也展现了其”短视”的缺点,红线走了共65个格子,但蓝箭头方向只走了45个格子。

最后

还有一种方案就是直接计算起点到终点的路径,这样可以节省一点计算开销。如下方右图,左图为广度优先算法。

了解了贪婪最佳优先算法后,下一篇文章会在本文基础上讲A* 寻路。

java 寻路算法_寻路算法-贪婪最佳优先算法相关推荐

  1. Python_机器学习_算法_第1章_K-近邻算法

    Python_机器学习_算法_第1章_K-近邻算法 文章目录 Python_机器学习_算法_第1章_K-近邻算法 K-近邻算法 学习目标 1.1 K-近邻算法简介 学习目标 1 什么是K-近邻算法 1 ...

  2. 路径规划算法_自动驾驶汽车路径规划算法浅析

    自动驾驶汽车的路径规划算法最早源于机器人的路径规划研究,但是就工况而言却比机器人的路径规划复杂得多,自动驾驶车辆需要考虑车速.道路的附着情况.车辆最小转弯半径.外界天气环境等因素. 本文将为大家介绍四 ...

  3. 作业调度算法【平均周转时间、平均带权周转时间、先来先服务FCFS、短作业优先SJF、高优先权(级)算法FPF、高响应比优先算法HRRN】

    文章目录 先来先服务算法(FCFS) 短作业优先算法(SJF).短进程优先算法(SPF) 周转时间和带权周转时间 高优先权(级)调度算法FPF 高响应比优先调度算法HRRN 先来先服务算法(FCFS) ...

  4. java实现apriori算法_七大经典、常用排序算法的原理、Java 实现以及算法分析

    0. 前言 大家好,我是多选参数的程序员,一个正再 neng 操作系统.学数据结构和算法以及 Java 的硬核菜鸡.数据结构和算法是我准备新开的坑,主要是因为自己再这块确实很弱,需要大补(残废了一般) ...

  5. weka java 分类算法_使用Weka快速实践机器学习算法

    [译者注]在当下人工智能火爆发展的局面,每时每刻都有新的技术在诞生,但如果你是一个新手,Weka或许能帮助你直观.快速的感受机器学习带来的解决问题的新思路. Weka使机器学习的应用变得简单.高效并且 ...

  6. 错误录入 算法_如何使用验证错误率确定算法输出之间的关系

    错误录入 算法 Monument (www.monument.ai) enables you to quickly apply algorithms to data in a no-code inte ...

  7. 沃舍尔算法_[数据结构拾遗]图的最短路径算法

    前言 本专题旨在快速了解常见的数据结构和算法. 在需要使用到相应算法时,能够帮助你回忆出常用的实现方案并且知晓其优缺点和适用环境.并不涉及十分具体的实现细节描述. 图的最短路径算法 最短路径问题是图论 ...

  8. 非抢占式优先算法例题_非抢占短作业优先算法源代码(C语言)

    #include #include #define MAX 5 //进程数 /*短作业优先算法*/ struct pro { int num; //进程名 int arriveTime; //到达时间 ...

  9. 利用python语言实现分类算法_使用python实现kNN分类算法

    k-近邻算法是基本的机器学习算法,算法的原理非常简单: 输入样本数据后,计算输入样本和参考样本之间的距离,找出离输入样本距离最近的k个样本,找出这k个样本中出现频率最高的类标签作为输入样本的类标签,很 ...

最新文章

  1. 聊城中考计算机试题及答案,初中微机模拟考试试题(word版).doc
  2. myeclipse 如何显示序号
  3. Ocelot简易教程(一)之Ocelot是什么
  4. python手机销售系统详细设计_数据库详细设计文档 .doc
  5. Mybatis3(3)动态 SQL
  6. 休眠和UUID标识符
  7. simulink同步发电机模型_基于Speedgoat的永磁同步电机控制Demo
  8. 语言软件生成outsid_常用的C语言开发工具有哪些
  9. (附源码)微信小程序 Demo
  10. 盘点JavaScript设计模式(常用十五大设计模式)
  11. 就业、养老、住房、出行等领域稳步前行 这一年,民生改善实实在在
  12. 世界经典名车中英名称对照
  13. 将dubbo暴露HTTP服务
  14. python模拟微信登录公众号_Python3微信公众平台requests模拟登陆
  15. win7如何修改html图标,Win7如何修改桌面图标
  16. 坑!阿里云对象存储OSS收费细则不只是存储还有其他扣费项
  17. python-scrapy爬虫框架爬取王者荣耀英雄皮肤图片和技能信息
  18. 通信软件基础B-重庆邮电大学-Java-编程实现一个简单的聊天程序-多线程编程实现
  19. Boosting 介绍和 Python 实现
  20. python正则表达式如何匹配“+”,“*”

热门文章

  1. ubuntu 安装kde桌面_给Ubuntu安装KDE桌面 [转]
  2. js实现前端页面跳转后操作新页面
  3. 忘记 iOS 的访问限制密码,如何找回或重设?
  4. uniap uni.showModal默认按钮自定义设置
  5. springboot cron定时器
  6. 安卓股票悬浮窗_Android 实现可任意拖动的悬浮窗功能(类似悬浮球)
  7. 大数据学习笔记之三十七 数据挖掘算法之关联分析
  8. 功能实现思路、逻辑思路、功能、逻辑
  9. Python中GIL详解
  10. hadoop+spark重新搭建