PHP实现基于回溯法求解迷宫问题的方法详解


Posted in PHP onAugust 17, 2017

本文实例讲述了PHP实现基于回溯法求解迷宫问题的方法。分享给大家供大家参考,具体如下:

引言

最近在leetcode上看了些算法题,有些看着很简单的很常用的东西,竟然一下子想不出来怎么求解,比如说:实现sqrt函数,求数组的排列。如果高数学的不好,这些看似简单的问题,第一次碰到也会感觉很难求解,当然了,今天要说的是这样一个问题,求解迷宫的所有解,这个问题的求解用到了回溯法的思想,不了解这个思想的话,很多稍微复杂点的问题都很难解了。

问题描述

这个问题是在实在瞎逛的时候碰到的,具体哪里记不太清了。

1   1   1   1
0   1   0   1
0   1   0   1
0   1   1   1

上面是一个迷宫,左上角是入口,右下角是出口,小萌(对,你没看错,是长了草的小明)从入口进入,从出口逃出(1个小时逃不出会被X怪物吃掉),其中1表示可以通行,0表示不能通行,只能向右和向下两个方向走,求出所有的小萌可能逃生的路线。

这个问题看似挺简单,一下就可以看到答案,但是将思想翻译为代码却不知道从何入手了。

如何解决

解决这个问题的一种方案就是回溯法,先一起看看回溯法(百度百科)的定义:

回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

我的思路:

1. 对上面的迷宫进行坐标化,左上角是(0,0),右下角是(3,3),其他点分散在坐标系中
2. 从(0,0)开始
3. 从给定的坐标点开始,先向右搜索,是1的话继续,是0的话向下搜索,搜索前记录当前已经搜索过的坐标
4. 当坐标等于(3,3)的时候就是一个回溯点了,这个时候也返回
5. 只要不越界,重复第三步骤

看看我的PHP实现:

<?php
$nums = [
  [1,1,1,1,1,1],
  [0,1,0,1,0,1],
  [0,1,0,1,0,1],
  [0,1,1,1,1,1]
];
function getRet($data, $x, $y, &$result=[], $record)
{
  $snapshort = [];
  $xL = count($data) - 1;
  $yL = count($data[0]) - 1;
  if($x > $xL || $y > $yL) {
    //跑到迷宫不存在的空间了,这种事情绝对不能发生
    return;
  }
  if($data[$x][$y] == "0") {
    //是0的话停止继续前进,退回上一状态
    return;
  } elseif($data[$x][$y] == "1") {
    //是1的话,记录最新的坐标到当前已找到的路径中,继续向前搜索
    //如果到达出口,记录答案并回溯
    $snapshort = array_merge($record, [[$x, $y]]);
    if($x == $xL && $y == $yL) {
      $result[] = array_merge($record, [[$x, $y]]);
      return;
    }
  } else {
    return;
  }
  //向有搜索
  //这里的$snapshort保存当前搜索位置的状态,等到下次回溯到这里的时候会用到
  getRet($data, $x, ++$y, $result, $snapshort);
  //向下搜索
  getRet($data, ++$x, --$y, $result, $snapshort);
}
//看个例子
$result = [];
getRet($nums, 0, 0, $result, []);
foreach ($result as $pos) {
  foreach ($pos as $xy) {
    echo "({$xy[0]},{$xy[1]}) => ";
  }
  echo "end\n";
}

输出结果

(0,0)=>(0,1)=>(0,2)=>(0,3)=>(0,4)=>(0,5)=>(1,5)=>(2,5)=>(3,5)=>end
(0,0)=>(0,1)=>(0,2)=>(0,3)=>(1,3)=>(2,3)=>(3,3)=>(3,4)=>(3,5)=>end
(0,0)=>(0,1)=>(1,1)=>(2,1)=>(3,1)=>(3,2)=>(3,3)=>(3,4)=>(3,5)=>end

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
PHP 和 MySQL 基础教程(四)
Oct 09 PHP
php实现网站插件机制的方法
Nov 10 PHP
php数组对百万数据进行排除重复数据的实现代码
Jun 08 PHP
在WAMP环境下搭建ZendDebugger php调试工具的方法
Jul 18 PHP
fgetcvs在linux的问题
Jan 15 PHP
PHP 基于文件头的文件类型验证类函数
May 01 PHP
关于PHPDocument 代码注释规范的总结
Jun 25 PHP
php表单提交与$_POST实例分析
Jan 26 PHP
php简单实现快速排序的方法
Apr 04 PHP
详解PHP匿名函数与注意事项
Mar 29 PHP
php实现图片上传、剪切功能
May 07 PHP
PHP字符串中抽取子串操作实例分析
Jun 22 PHP
PHP基于Closure类创建匿名函数的方法详解
Aug 17 #PHP
PHP编译configure时常见错误的总结
Aug 17 #PHP
基于PHP常用文件函数和目录函数整理
Aug 17 #PHP
PHP实现的堆排序算法详解
Aug 17 #PHP
基于php编程规范(详解)
Aug 17 #PHP
PHP数据库操作四:mongodb用法分析
Aug 16 #PHP
PHP Laravel 上传图片、文件等类封装
Aug 16 #PHP
You might like
特转载一高手总结PHP学习资源和链接.
2006/12/05 PHP
PHP 高级课程笔记 面向对象
2009/06/21 PHP
PHP定时执行计划任务的多种方法小结
2011/12/19 PHP
php获取服务器端mac和客户端mac的地址支持WIN/LINUX
2014/05/15 PHP
如何通过View::first使用Laravel Blade的动态模板详解
2017/09/21 PHP
JavaScript 申明函数的三种方法 每个函数就是一个对象(一)
2009/12/04 Javascript
js 字符串转化成数字的代码
2011/06/29 Javascript
JS、CSS以及img对DOMContentLoaded事件的影响
2014/08/12 Javascript
js 加密压缩出现bug解决方案
2014/11/25 Javascript
js实现动画特效的文字链接鼠标悬停提示的方法
2015/03/02 Javascript
JS控制网页动态生成任意行列数表格的方法
2015/03/09 Javascript
js由下向上不断上升冒气泡效果实例
2015/05/07 Javascript
javascript顺序加载图片的方法
2015/07/18 Javascript
jquery图片轮播特效代码分享
2020/04/20 Javascript
详解JavaScript对象类型
2016/06/16 Javascript
Bootstrap table两种分页示例
2016/12/23 Javascript
Vue指令的钩子函数使用方法
2017/03/20 Javascript
Postman模拟发送带token的请求方法
2018/03/31 Javascript
详解vue2.6插槽更新v-slot用法总结
2019/03/09 Javascript
简单介绍Python中的RSS处理
2015/04/13 Python
python 日志增量抓取实现方法
2018/04/28 Python
在python 不同时区之间的差值与转换方法
2019/01/14 Python
Python3.5内置模块之os模块、sys模块、shutil模块用法实例分析
2019/04/27 Python
python机器学习库scikit-learn:SVR的基本应用
2019/06/26 Python
六种酷炫Python运行进度条效果的实现代码
2020/07/17 Python
使用CSS3在触屏上为按钮实现激活效果
2013/09/27 HTML / CSS
使用canvas压缩图片大小的方法示例
2019/08/02 HTML / CSS
回门宴父母答谢词
2014/01/26 职场文书
电子银行营销方案
2014/02/22 职场文书
静心口服夜广告词
2014/03/20 职场文书
同学聚会策划方案
2014/06/06 职场文书
2015年人事专员工作总结
2015/04/29 职场文书
2015秋季小学开学寄语
2015/05/27 职场文书
中国梦宣传标语口号
2015/12/26 职场文书
《吃水不忘挖井人》教学反思
2016/02/22 职场文书
导游词之井冈山
2019/11/20 职场文书