严正声明:本文系作者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集中取出最好的结点nf值最小的结点)并检查之。如果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, &not_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) &&not_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算法求解二维迷宫问题相关推荐

  1. 【运筹优化】结合天际线启发式的蚁群算法求解二维矩形装箱问题 + Java代码实现

    文章目录 一.天际线启发式 二.蚁群算法结合天际线启发式 2.1 构建序列 2.1.1 思路一 2.1.2 思路二 2.1.3 思路N 三.Java代码实现 3.1 项目结构 3.2 Ant 3.3 ...

  2. 【运筹优化】蚁群算法求解二维矩形装箱问题(java代码实现)

    文章目录 1 前言 2 代码迁移 3 蚁群算法 3.1 蚂蚁类 Ant 3.2 蚁群算法类 ACO_Packing 4 运行结果 5 后话 [运筹优化]求解二维矩形装箱问题的算法合辑(Java代码实现 ...

  3. 基于Astar算法的二维栅格地图路径规划和避障MATLAB仿真

    目录 1.算法仿真效果 2.MATLAB源码 3.算法概述 4.部分参考文献 1.算法仿真效果 matlab2022a仿真结果如下: 2.MATLAB源码 %********************

  4. 【运筹优化】求解二维矩形装箱问题的算法合辑 + Java代码实现

    文章目录 一.算法合辑 1.1 结合自定义策略 1.1.1 结合自定义策略的禁忌搜索算法(98.80%) 1.2.1 结合自定义策略的蚁群算法(96.70%) 1.2 堆优化的天际线启发式算法(98. ...

  5. 利用高斯(Guass)算法求解2维的SVP向量

    利用Guass算法求解二维的SVP function [v1,v2 ] = Gauss_svp( v1 , v2 ) %作者:192152王旭 %功能:利用Guass算法求解2维的SVP向量 %输入要 ...

  6. 求解二维矩形 Packing 问题的一种优美度枚举 算法的个人心得1

    求解二维矩形 Packing 问题的一种优美度枚举 算法的个人心得 个人思考: 10.14: 提出了基于 "角区"的基本算法 什么是角区? 定义4 (角区) 矩形框中由块或者矩形框 ...

  7. 二维对流方程matlab求解,二维对流扩散方程的有限元计算方法

    冯立伟+张成+屈福志 " " " 摘要:针对二维对流扩散方程边值问题,采用三角形剖分,使用二维线性有限元进行计算分析.采用matlab编写了计算程序,使用算例进行了数值实 ...

  8. MATLAB语言实现模拟退火算法求解n维变量的最小值问题

    在给定定义域,对于求解函数对应的最优值问题.此处以模拟退火算法求解30维变量函数最小值问题举例(最大值问题也可转化成求解最小值问题). 其中,. 一.模拟退火算法简介 模拟退火算法(SA)来源于固体退 ...

  9. 《MATLAB智能算法30个案例》:第23章 基于蚁群算法的二维路径规划算法

    <MATLAB智能算法30个案例>:第23章 基于蚁群算法的二维路径规划算法 1. 前言 2. MATLAB 仿真示例 3. 小结 1. 前言 <MATLAB智能算法30个案例分析& ...

最新文章

  1. 人脑是怎么防止梯度消失和梯度爆炸的?
  2. matlab极大值点个数,求一组数的极大值个数
  3. 每日一皮:这一定是“宅”的极致了...
  4. LeetCode算法题12:递归和回溯-字符串中的回溯问题
  5. [官方教程] [ES4封装教程]1.使用 VMware Player 创建适合封装的虚拟机
  6. hdu4841 圆桌问题-vector容器模拟
  7. 【操作系统复习】系统调用
  8. win7系统下的打印机不能扫描
  9. python数据结构之字典(dict)——超详细
  10. C语言中用链表构建栈讲解,C语言数据结构之使用链表模拟栈的实例
  11. java execlp_Linux下的C程序,使用函数execlp运行Shell命令
  12. Elasticsearch顶尖高手系列:高手进阶篇(二)
  13. julia语言 python解释器_Julia官宣:为机器学习构建一种语言和编译器
  14. 半角数字验证 Encoding
  15. 一位营销总监的辞职信
  16. 深度学习上采样下采样概念以及实现
  17. 最完整的磁性材料行业现状及发展前景分析,长文预警
  18. 论文阅读:Generating Abstractive Summaries with Finetuned Language Models
  19. 谷歌浏览器插件HackBar安装方法(详细教程)
  20. 网络工程师经典技术面试题系列华为数通 STP关键理论与实战

热门文章

  1. 如何让外网访问你的电脑
  2. 对“师德”的一点体会
  3. c++实习项目3D模型显示系统
  4. 014-Ambari功能介绍
  5. 在Salesforce Lightning Experience(闪电体验)提高性能和速度
  6. win10操作系统无法安装i8
  7. Android移动支付(支付宝支付2017最新接入详解)
  8. 深入浅出Python机器学习4——广义线性模型
  9. 【四足机器人】SOLO技术详解--(1)介绍(2)平台和机器人概述【翻译】
  10. 为什么qt改不了ui的字体_为您的UI选择最佳字体