使用AStar算法求解二维迷宫问题
严正声明:本文系作者davidhopper原创,未经许可,不得转载。
题目描述
定义一个二维数组N*M(其中2<=N<=10;2<=M<=10),如5 × 5数组下所示:
int maze[5][5] = {0, 1, 0, 0, 0,0, 1, 0, 1, 0,0, 0, 0, 0, 0,0, 1, 1, 1, 0,0, 0, 0, 1, 0,
};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。入口点为[0,0],即第一空格是可以走的路。
Input
一个N × M的二维数组,表示一个迷宫。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。
Output
左上角到右下角的最短路径,格式如样例所示。
Sample Input
5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
Sample Output
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)
输入描述
输入两个整数,分别表示二位数组的行数,列数。再输入相应的数组,其中的1表示墙壁,0表示可以走的路。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。
输出描述
左上角到右下角的最短路径,格式如样例所示。
示例1
输入
6 5
0 0 0 1 1
1 1 0 1 1
1 1 0 0 1
1 1 1 0 1
1 1 1 0 1
1 1 1 0 0
输出
(0,0)
(0,1)
(0,2)
(1,2)
(2,2)
(2,3)
(3,3)
(4,3)
(5,3)
(5,4)
答案
一般都会使用回溯法求解,本文使用效率更高的A*算法求解(杀鸡用牛刀)。A*算法的原理可参考这篇文章:A星算法详解。
如果不考虑具体实现代码,A*算法是相当简单的。有两个集合,OPEN
集和CLOSED
集。其中OPEN
集保存待考察的结点。开始时,OPEN
集只包含一个元素:初始结点。CLOSED
集保存已考查过的结点。开始时,CLOSED
集是空的。如果绘成图,OPEN
集就是被访问区域的边境(frontier),而CLOSED
集则是被访问区域的内部(interior)。每个结点同时保存其父结点的指针,以便反向溯源。
在主循环中重复地从OPEN
集中取出最好的结点n
(f
值最小的结点)并检查之。如果n
是目标结点,则我们的任务完成了。否则,从OPEN
集中删除结点n
并将其加入CLOSED
集。然后检查它的邻居n’
。如果邻居n’
在CLOSED
集中,表明该邻居已被检查过,不必再次考虑(若你确实需要检查结点n’
的g
值是否更小,可进行相关检查,若其g
值更小,则将该结点从CLOSED
集中删除。除特殊情况外,一般不需如此处理,本文不进行这种检查);如果n’
在OPEN
集中,那么该结点今后肯定会被考察,现在不必考虑它。否则,把它加入OPEN
集,把它的父结点设为n
。
A*搜索算法的核心就在于如何设计一个好的启发代价函数:
f(n)=g(n)+h(n)f(n)=g(n)+h(n)f(n)=g(n)+h(n)
其中f(n)f(n)f(n)是每个节点的代价值,它由两部分组成,g(n)g(n)g(n)表示从起点到搜索点的代价,h(n)h(n)h(n)表示从搜索点到目标点的代价,h(n)h(n)h(n)设计的好坏,直接影响到A*算法的效率。h(n)h(n)h(n)的权重越大,收敛速度越快,但不能保证得到最优解。
在采用A*算法对迷宫路径求解中,g(n)g(n)g(n)和h(n)h(n)h(n)函数都采用曼哈顿距离:
d(i,j)=∣x1−x2∣+∣y1−y2∣d(i,j)=|x_1−x_2|+|y_1−y_2|d(i,j)=∣x1−x2∣+∣y1−y2∣
即针对当前节点,都会计算其到起始节点和终止结点的曼哈顿距离。
具体代码
#include <algorithm>
#include <iostream>
#include <list>
#include <memory>
#include <vector>struct PathNode {PathNode(const int row, const int col,const int f = std::numeric_limits<int>::max(),const std::shared_ptr<PathNode>& parent = nullptr): row_(row), col_(col), f_(f), parent_(parent) {}bool operator==(const PathNode& other) const {return row_ == other.row_ && col_ == other.col_;}int row_;int col_;// f = g + hint f_;// parent nodestd::shared_ptr<PathNode> parent_;
};void AStarSearch(const std::vector<std::vector<int>>& maze_mat,std::list<std::shared_ptr<PathNode>>& solution);int main() {int row, col;while (std::cin >> row && std::cin >> col) {std::vector<std::vector<int>> maze_mat(row, std::vector<int>(col));for (int i = 0; i < row; ++i) {for (int j = 0; j < col; ++j) {std::cin >> maze_mat[i][j];}}std::list<std::shared_ptr<PathNode>> solution;AStarSearch(maze_mat, solution);for (const auto& node : solution) {std::cout << "(" << node->row_ << "," << node->col_ << ")" << std::endl;}}return 0;
}void AStarSearch(const std::vector<std::vector<int>>& maze_mat,std::list<std::shared_ptr<PathNode>>& solution) {if (maze_mat.empty() || maze_mat[0].empty()) {return;}int start_row = 0;int start_col = 0;int end_row = maze_mat.size() - 1;int end_col = maze_mat[0].size() - 1;std::list<std::shared_ptr<PathNode>> open_list, closed_list;std::shared_ptr<PathNode> end_node = nullptr;auto start_node = std::make_shared<PathNode>(start_row, start_col);open_list.emplace_back(start_node);// Internal functions written in Lambda expressionsauto calc_f_val_func = [&start_row, &start_col, &end_row, &end_col](const int row, const int col) {int g_val = std::abs(row - start_row) + std::abs(col - start_col);int h_val = std::abs(end_row - row) + std::abs(end_col - col);// The heuristic coefficient has a great influence on the search speed. The// larger it is, the faster the convergence speed, but it cannot// guarantee the optimal solution is obtained.int h_coeff = 3;return g_val + h_coeff * h_val;};auto not_exist_func = [](const std::list<std::shared_ptr<PathNode>>& list,std::shared_ptr<PathNode>& node) {return std::find(list.begin(), list.end(), node) == list.end();};auto handle_child_node_func = [&open_list, &closed_list, &start_row,&start_col, &end_row, &end_col, &maze_mat,&calc_f_val_func, ¬_exist_func](const std::shared_ptr<PathNode>& cur_node,const int row, const int col) {if (row < start_row || col < start_col || row > end_row || col > end_col) {return;}// Wallif (maze_mat[row][col] > 0) {return;}auto child_node = std::make_shared<PathNode>(row, col);if (not_exist_func(open_list, child_node) &¬_exist_func(closed_list, child_node)) {child_node->f_ = calc_f_val_func(row, col);child_node->parent_ = cur_node;open_list.emplace_back(child_node);}};// A* algorithmwhile (!open_list.empty()) {// Get the node with minimal f valueauto min_iter = std::min_element(open_list.begin(), open_list.end(),[](const std::shared_ptr<PathNode>& lhs,const std::shared_ptr<PathNode>& rhs) { return lhs->f_ < rhs->f_; });if (min_iter == open_list.end()) {break;}auto min_node = *min_iter;// std::cout << "min_node: " << min_node << ", " << min_node->row_ << ", "// << min_node->col_ << ", " << min_node->f_ << std::endl;closed_list.emplace_back(min_node);open_list.erase(min_iter);if (min_node->row_ == end_row && min_node->col_ == end_col) {end_node = min_node;break;} else {// Handle child nodes in four directions.// Northhandle_child_node_func(min_node, min_node->row_ - 1, min_node->col_);// Easthandle_child_node_func(min_node, min_node->row_, min_node->col_ + 1);// Southhandle_child_node_func(min_node, min_node->row_ + 1, min_node->col_);// Westhandle_child_node_func(min_node, min_node->row_, min_node->col_ - 1);}}if (end_node != nullptr) {do {solution.emplace_back(end_node);end_node = end_node->parent_;} while (end_node != nullptr);// Reverse the list.solution.reverse();}
}
使用AStar算法求解二维迷宫问题相关推荐
- 【运筹优化】结合天际线启发式的蚁群算法求解二维矩形装箱问题 + Java代码实现
文章目录 一.天际线启发式 二.蚁群算法结合天际线启发式 2.1 构建序列 2.1.1 思路一 2.1.2 思路二 2.1.3 思路N 三.Java代码实现 3.1 项目结构 3.2 Ant 3.3 ...
- 【运筹优化】蚁群算法求解二维矩形装箱问题(java代码实现)
文章目录 1 前言 2 代码迁移 3 蚁群算法 3.1 蚂蚁类 Ant 3.2 蚁群算法类 ACO_Packing 4 运行结果 5 后话 [运筹优化]求解二维矩形装箱问题的算法合辑(Java代码实现 ...
- 基于Astar算法的二维栅格地图路径规划和避障MATLAB仿真
目录 1.算法仿真效果 2.MATLAB源码 3.算法概述 4.部分参考文献 1.算法仿真效果 matlab2022a仿真结果如下: 2.MATLAB源码 %********************
- 【运筹优化】求解二维矩形装箱问题的算法合辑 + Java代码实现
文章目录 一.算法合辑 1.1 结合自定义策略 1.1.1 结合自定义策略的禁忌搜索算法(98.80%) 1.2.1 结合自定义策略的蚁群算法(96.70%) 1.2 堆优化的天际线启发式算法(98. ...
- 利用高斯(Guass)算法求解2维的SVP向量
利用Guass算法求解二维的SVP function [v1,v2 ] = Gauss_svp( v1 , v2 ) %作者:192152王旭 %功能:利用Guass算法求解2维的SVP向量 %输入要 ...
- 求解二维矩形 Packing 问题的一种优美度枚举 算法的个人心得1
求解二维矩形 Packing 问题的一种优美度枚举 算法的个人心得 个人思考: 10.14: 提出了基于 "角区"的基本算法 什么是角区? 定义4 (角区) 矩形框中由块或者矩形框 ...
- 二维对流方程matlab求解,二维对流扩散方程的有限元计算方法
冯立伟+张成+屈福志 " " " 摘要:针对二维对流扩散方程边值问题,采用三角形剖分,使用二维线性有限元进行计算分析.采用matlab编写了计算程序,使用算例进行了数值实 ...
- MATLAB语言实现模拟退火算法求解n维变量的最小值问题
在给定定义域,对于求解函数对应的最优值问题.此处以模拟退火算法求解30维变量函数最小值问题举例(最大值问题也可转化成求解最小值问题). 其中,. 一.模拟退火算法简介 模拟退火算法(SA)来源于固体退 ...
- 《MATLAB智能算法30个案例》:第23章 基于蚁群算法的二维路径规划算法
<MATLAB智能算法30个案例>:第23章 基于蚁群算法的二维路径规划算法 1. 前言 2. MATLAB 仿真示例 3. 小结 1. 前言 <MATLAB智能算法30个案例分析& ...
最新文章
- 人脑是怎么防止梯度消失和梯度爆炸的?
- matlab极大值点个数,求一组数的极大值个数
- 每日一皮:这一定是“宅”的极致了...
- LeetCode算法题12:递归和回溯-字符串中的回溯问题
- [官方教程] [ES4封装教程]1.使用 VMware Player 创建适合封装的虚拟机
- hdu4841 圆桌问题-vector容器模拟
- 【操作系统复习】系统调用
- win7系统下的打印机不能扫描
- python数据结构之字典(dict)——超详细
- C语言中用链表构建栈讲解,C语言数据结构之使用链表模拟栈的实例
- java execlp_Linux下的C程序,使用函数execlp运行Shell命令
- Elasticsearch顶尖高手系列:高手进阶篇(二)
- julia语言 python解释器_Julia官宣:为机器学习构建一种语言和编译器
- 半角数字验证 Encoding
- 一位营销总监的辞职信
- 深度学习上采样下采样概念以及实现
- 最完整的磁性材料行业现状及发展前景分析,长文预警
- 论文阅读:Generating Abstractive Summaries with Finetuned Language Models
- 谷歌浏览器插件HackBar安装方法(详细教程)
- 网络工程师经典技术面试题系列华为数通 STP关键理论与实战