回溯法解迷宮問題

WBOY
發布: 2016-07-30 13:29:33
原創
976 人瀏覽過

引言

最近在leetcode上看了些算法題,有些看著很簡單的很常用的東西,竟然一下子想不出來怎麼求解,比如說:實現sqrt函數,求數組的排列。如果高數學的不好,這些看似簡單的問題,第一次碰到也會感覺很難求解,當然了,今天要說的是這樣一個問題,求解迷宮的所有解,這個問題的求解用到了回溯法的思想,不了解這個思想的話,很多稍微複雜點的問題都很難解了。

問題描述

這個問題是在實在瞎逛的時候碰到的,具體哪裡記不太清了。

<code>1   1   1   1

0   1   0   1

0   1   0   1

0   1   1   1</code>
登入後複製

上面是一個迷宮,左上角是入口,右下角是出口,小萌(對,你沒看錯,是長了草的小明)從入口進入,從出口逃出(1個小時逃不出會被X怪物吃掉),其中1表示可以通行,0表示不能通行,只能向右和向下兩個方向走,求出所有的小萌可能逃生的路線。

這個問題看似挺簡單,一下就可以看到答案,但是將思想翻譯為程式碼卻不知道從何入手了。

如何解決

解決這個問題的一個方案就是回溯法,先一起看看回溯法(百度百科)的定義:

回溯法(探索與回溯法)是一種選優搜尋法,又稱為試探法,按選優條件向前搜索,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術為回溯法,而滿足回溯條件的某個狀態的點稱為“回溯點”。

我的思路:

  • 對上面的迷宮進行坐標化,左上角是(0,0),右下角是(3,3),其他點分散在坐標系中
  • 從(0, 0)開始
  • 從給定的坐標點開始,先向右搜索,是1的話繼續,是0的話向下搜索,搜索前記錄當前已經搜索過的坐標
  • 當坐標等於(3,3 )的時候就是一個回溯點了,這個時候也返回
  • 只要不越界,重複第三步驟

看看我的PHP實現:

<code><?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</code>
登入後複製

以上就介紹了回溯法解迷宮問題,包括了方面的內容,希望對PHP教程有興趣的朋友有幫助。

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!