PHP實(shí)現(xiàn)基于回溯法求解迷宮問題的方法詳解
本文實(shí)例講述了PHP實(shí)現(xiàn)基于回溯法求解迷宮問題的方法。分享給大家供大家參考,具體如下:
引言
最近在leetcode上看了些算法題,有些看著很簡(jiǎn)單的很常用的東西,竟然一下子想不出來(lái)怎么求解,比如說:實(shí)現(xiàn)sqrt函數(shù),求數(shù)組的排列。如果高數(shù)學(xué)的不好,這些看似簡(jiǎn)單的問題,第一次碰到也會(huì)感覺很難求解,當(dāng)然了,今天要說的是這樣一個(gè)問題,求解迷宮的所有解,這個(gè)問題的求解用到了回溯法的思想,不了解這個(gè)思想的話,很多稍微復(fù)雜點(diǎn)的問題都很難解了。
問題描述
這個(gè)問題是在實(shí)在瞎逛的時(shí)候碰到的,具體哪里記不太清了。
1 1 1 1
0 1 0 1
0 1 0 1
0 1 1 1
上面是一個(gè)迷宮,左上角是入口,右下角是出口,小萌(對(duì),你沒看錯(cuò),是長(zhǎng)了草的小明)從入口進(jìn)入,從出口逃出(1個(gè)小時(shí)逃不出會(huì)被X怪物吃掉),其中1表示可以通行,0表示不能通行,只能向右和向下兩個(gè)方向走,求出所有的小萌可能逃生的路線。
這個(gè)問題看似挺簡(jiǎn)單,一下就可以看到答案,但是將思想翻譯為代碼卻不知道從何入手了。
如何解決
解決這個(gè)問題的一種方案就是回溯法,先一起看看回溯法(百度百科)的定義:
回溯法(探索與回溯法)是一種選優(yōu)搜索法,又稱為試探法,按選優(yōu)條件向前搜索,以達(dá)到目標(biāo)。但當(dāng)探索到某一步時(shí),發(fā)現(xiàn)原先選擇并不優(yōu)或達(dá)不到目標(biāo),就退回一步重新選擇,這種走不通就退回再走的技術(shù)為回溯法,而滿足回溯條件的某個(gè)狀態(tài)的點(diǎn)稱為“回溯點(diǎn)”。
我的思路:
1. 對(duì)上面的迷宮進(jìn)行坐標(biāo)化,左上角是(0,0),右下角是(3,3),其他點(diǎn)分散在坐標(biāo)系中
2. 從(0,0)開始
3. 從給定的坐標(biāo)點(diǎn)開始,先向右搜索,是1的話繼續(xù),是0的話向下搜索,搜索前記錄當(dāng)前已經(jīng)搜索過的坐標(biāo)
4. 當(dāng)坐標(biāo)等于(3,3)的時(shí)候就是一個(gè)回溯點(diǎn)了,這個(gè)時(shí)候也返回
5. 只要不越界,重復(fù)第三步驟
看看我的PHP實(shí)現(xiàn):
<?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) { //跑到迷宮不存在的空間了,這種事情絕對(duì)不能發(fā)生 return; } if($data[$x][$y] == "0") { //是0的話停止繼續(xù)前進(jìn),退回上一狀態(tài) return; } elseif($data[$x][$y] == "1") { //是1的話,記錄最新的坐標(biāo)到當(dāng)前已找到的路徑中,繼續(xù)向前搜索 //如果到達(dá)出口,記錄答案并回溯 $snapshort = array_merge($record, [[$x, $y]]); if($x == $xL && $y == $yL) { $result[] = array_merge($record, [[$x, $y]]); return; } } else { return; } //向有搜索 //這里的$snapshort保存當(dāng)前搜索位置的狀態(tài),等到下次回溯到這里的時(shí)候會(huì)用到 getRet($data, $x, ++$y, $result, $snapshort); //向下搜索 getRet($data, ++$x, --$y, $result, $snapshort); } //看個(gè)例子 $result = []; getRet($nums, 0, 0, $result, []); foreach ($result as $pos) { foreach ($pos as $xy) { echo "({$xy[0]},{$xy[1]}) => "; } echo "end\n"; }
輸出結(jié)果
(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
更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《PHP數(shù)據(jù)結(jié)構(gòu)與算法教程》、《php程序設(shè)計(jì)算法總結(jié)》、《php字符串(string)用法總結(jié)》、《PHP數(shù)組(Array)操作技巧大全》、《PHP常用遍歷算法與技巧總結(jié)》及《PHP數(shù)學(xué)運(yùn)算技巧總結(jié)》
希望本文所述對(duì)大家PHP程序設(shè)計(jì)有所幫助。
相關(guān)文章
php簡(jiǎn)單實(shí)現(xiàn)sql防注入的方法
這篇文章主要介紹了php簡(jiǎn)單實(shí)現(xiàn)sql防注入的方法,涉及addslashes函數(shù)的使用及正則過濾的相關(guān)技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2016-04-04PHP中一些可以替代正則表達(dá)式函數(shù)的字符串操作函數(shù)
這篇文章主要介紹了PHP中一些可以替代正則表達(dá)式函數(shù)的字符串操作函數(shù),本文總結(jié)的是一些比較特別的字符串操作函數(shù),需要的朋友可以參考下2014-11-11PHP實(shí)現(xiàn)簡(jiǎn)單的模板引擎功能示例
這篇文章主要介紹了PHP實(shí)現(xiàn)簡(jiǎn)單的模板引擎功能,結(jié)合實(shí)例形式詳細(xì)分析了PHP實(shí)現(xiàn)模板引擎功能的模版類、編譯類、控制器類及模板文件等實(shí)現(xiàn)方法與相關(guān)操作技巧,需要的朋友可以參考下2017-09-09