哈哈哈哈哈操欧洲电影,久草网在线,亚洲久久熟女熟妇视频,麻豆精品色,久久福利在线视频,日韩中文字幕的,淫乱毛视频一区,亚洲成人一二三,中文人妻日韩精品电影

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

如何用回溯算法來解決數(shù)獨問題

算法與數(shù)據(jù)結構 ? 來源:labuladong ? 作者:labuladong ? 2022-04-26 14:47 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

經(jīng)常拿回溯算法來說事兒的,無非就是八皇后問題和數(shù)獨問題了。那我們今天就通過實際且有趣的例子來講一下如何用回溯算法來解決數(shù)獨問題。

一、直觀感受

說實話我小的時候也嘗試過玩數(shù)獨游戲,但從來都沒有完成過一次。做數(shù)獨是有技巧的,我記得一些比較專業(yè)的數(shù)獨游戲軟件,他們會教你玩數(shù)獨的技巧,不過在我看來這些技巧都太復雜,我根本就沒有興趣看下去。

不過自從我學習了算法,多困難的數(shù)獨問題都攔不住我了。下面是我用程序完成數(shù)獨的一個例子:

372cdc3c-c3bd-11ec-bce3-dac502259ad0.gif

PS:GIF 可能出現(xiàn) bug,若卡住點開查看即可,下同。

這是一個安卓手機中的數(shù)獨游戲,我使用一個叫做 Auto.js 的腳本引擎,配合回溯算法來實現(xiàn)自動完成填寫,并且算法記錄了執(zhí)行次數(shù)。

在后文,我會給出該腳本的實現(xiàn)思路代碼以及軟件工具的下載,你也可以拿來裝13用。

可以觀察到前兩次都執(zhí)行了 1 萬多次,而最后一次只執(zhí)行了 100 多次就算出了答案,這說明對于不同的局面,回溯算法得到答案的時間是不相同的。

那么計算機如何解決數(shù)獨問題呢?其實非常的簡單,就是窮舉嘛,下面我可視化了求解過程:

37639858-c3bd-11ec-bce3-dac502259ad0.gif

算法的核心思路非常非常的簡單,就是對每一個空著的格子窮舉 1 到 9,如果遇到不合法的數(shù)字(在同一行或同一列或同一個 3×3 的區(qū)域中存在相同的數(shù)字)則跳過,如果找到一個合法的數(shù)字,則繼續(xù)窮舉下一個空格子。

對于數(shù)獨游戲,也許我們還會有另一個誤區(qū):就是下意識地認為如果給定的數(shù)字越少那么這個局面的難度就越大。

這個結論對人來說應該沒毛病,但對于計算機而言,給的數(shù)字越少,反而窮舉的步數(shù)就越少,得到答案的速度越快,至于為什么,我們后面探討代碼實現(xiàn)的時候會講。

上一個 GIF 是最后一關 70 關,下圖是第 52 關,數(shù)字比較多,看起來似乎不難,但是我們看一下算法執(zhí)行的過程:

378d7132-c3bd-11ec-bce3-dac502259ad0.gif

可以看到算法在前兩行窮舉了半天都沒有走出去,由于時間原因我就沒有繼續(xù)錄制了,事實上,這個局面窮舉的次數(shù)大概是上一個局面的 10 倍。

言歸正傳,下面我們就來具體探討一下如何用算法來求解數(shù)獨問題,順便說說我是如何可視化這個求解過程的。

二、代碼實現(xiàn)

首先,我們不用管游戲的 UI,先單純地解決回溯算法,LeetCode 第 37 題就是解數(shù)獨的問題,算法函數(shù)簽名如下:

voidsolveSudoku(char[][]board);

輸入是一個9x9的棋盤,空白格子用點號字符.表示,算法需要在原地修改棋盤,將空白格子填上數(shù)字,得到一個可行解。

至于數(shù)獨的要求,大家想必都很熟悉了,每行,每列以及每一個 3×3 的小方格都不能有相同的數(shù)字出現(xiàn)。那么,現(xiàn)在我們直接套回溯框架即可求解。

前文回溯算法詳解,已經(jīng)寫過了回溯算法的套路框架,如果還沒看過那篇文章的,建議先看看。

回憶剛才的 GIF 圖片,我們求解數(shù)獨的思路很簡單粗暴,就是對每一個格子所有可能的數(shù)字進行窮舉。對于每個位置,應該如何窮舉,有幾個選擇呢?

很簡單啊,從 1 到 9 就是選擇,全部試一遍不就行了

//對board[i][j]進行窮舉嘗試
voidbacktrack(char[][]board,inti,intj){
intm=9,n=9;
for(charch='1';ch<=?'9';ch++){
//做選擇
board[i][j]=ch;
//繼續(xù)窮舉下一個
backtrack(board,i,j+1);
//撤銷選擇
board[i][j]='.';
}
}

emmm,再繼續(xù)細化,并不是 1 到 9 都可以取到的,有的數(shù)字不是不滿足數(shù)獨的合法條件嗎?而且現(xiàn)在只是給j加一,那如果j加到最后一列了,怎么辦?

很簡單,當j到達超過每一行的最后一個索引時,轉(zhuǎn)為增加i開始窮舉下一行,并且在窮舉之前添加一個判斷,跳過不滿足條件的數(shù)字

voidbacktrack(char[][]board,inti,intj){
intm=9,n=9;
if(j==n){
//窮舉到最后一列的話就換到下一行重新開始。
backtrack(board,i+1,0);
return;
}

//如果該位置是預設的數(shù)字,不用我們操心
if(board[i][j]!='.'){
backtrack(board,i,j+1);
return;
}

for(charch='1';ch<=?'9';ch++){
//如果遇到不合法的數(shù)字,就跳過
if(!isValid(board,i,j,ch))
continue;

board[i][j]=ch;
backtrack(board,i,j+1);
board[i][j]='.';
}
}

//判斷board[r][c]是否可以填入n
booleanisValid(char[][]board,intr,intc,charn){
for(inti=0;i9;i++){
//判斷行是否存在重復
if(board[r][i]==n)returnfalse;
//判斷列是否存在重復
if(board[i][c]==n)returnfalse;
//判斷3x3方框是否存在重復
if(board[(r/3)*3+i/3][(c/3)*3+i%3]==n)
returnfalse;
}
returntrue;
}

emmm,現(xiàn)在基本上差不多了,還剩最后一個問題:這個算法沒有 base case,永遠不會停止遞歸。這個好辦,什么時候結束遞歸?顯然r == m的時候就說明窮舉完了最后一行,完成了所有的窮舉,就是 base case。

另外,前文也提到過,為了減少復雜度,我們可以讓backtrack函數(shù)返回值為boolean,如果找到一個可行解就返回 true,這樣就可以阻止后續(xù)的遞歸。只找一個可行解,也是題目的本意。

最終代碼修改如下:

booleanbacktrack(char[][]board,inti,intj){
intm=9,n=9;
if(j==n){
//窮舉到最后一列的話就換到下一行重新開始。
returnbacktrack(board,i+1,0);
}
if(i==m){
//找到一個可行解,觸發(fā)basecase
returntrue;
}

if(board[i][j]!='.'){
//如果有預設數(shù)字,不用我們窮舉
returnbacktrack(board,i,j+1);
}

for(charch='1';ch<=?'9';ch++){
//如果遇到不合法的數(shù)字,就跳過
if(!isValid(board,i,j,ch))
continue;

board[i][j]=ch;
//如果找到一個可行解,立即結束
if(backtrack(board,i,j+1)){
returntrue;
}
board[i][j]='.';
}
//窮舉完1~9,依然沒有找到可行解,此路不通
returnfalse;
}

booleanisValid(char[][]board,intr,intc,charn){
//見上文
}

現(xiàn)在可以回答一下之前的問題,為什么有時候算法執(zhí)行的次數(shù)多,有時候少?為什么對于計算機而言,確定的數(shù)字越少,反而算出答案的速度越快?

我們已經(jīng)實現(xiàn)了一遍算法,掌握了其原理,回溯就是從 1 開始對每個格子窮舉,最后只要試出一個可行解,就會立即停止后續(xù)的遞歸窮舉。所以暴力試出答案的次數(shù)和隨機生成的棋盤關系很大,這個是說不準的。

那么你可能問,既然運行次數(shù)說不準,那么這個算法的時間復雜度是多少呢?

對于這種時間復雜度的計算,我們只能給出一個最壞情況,也就是 O(9^M),其中M是棋盤中空著的格子數(shù)量。你想嘛,對每個空格子窮舉 9 個數(shù),結果就是指數(shù)級的。

這個復雜度非常高,但稍作思考就能發(fā)現(xiàn),實際上我們并沒有真的對每個空格都窮舉 9 次,有的數(shù)字會跳過,有的數(shù)字根本就沒有窮舉,因為當我們找到一個可行解的時候就立即結束了,后續(xù)的遞歸都沒有展開。

這個 O(9^M) 的復雜度實際上是完全窮舉,或者說是找到所有可行解的時間復雜度。

如果給定的數(shù)字越少,相當于給出的約束條件越少,對于計算機這種窮舉策略來說,是更容易進行下去,而不容易走回頭路進行回溯的,所以說如果僅僅找出一個可行解,這種情況下窮舉的速度反而比較快。

至此,回溯算法就完成了,你可以用以上代碼通過 LeetCode 的判題系統(tǒng),下面我們來簡單說下我是如何把這個回溯過程可視化出來的。

三、算法可視化

讓算法幫我玩游戲的核心是算法,如果你理解了這個算法,剩下就是借助安卓腳本引擎 Auto.js 調(diào) API 操作手機了,工具我都放在后臺了,你等會兒就可以下載。

用偽碼簡單說下思路,我可以寫兩個函數(shù):

voidsetNum(Buttonb,charn){
//輸入一個方格,將該方格設置為數(shù)字n
}

voidcancelNum(Buttonb){
//輸入一個方格,將該方格上的數(shù)字撤銷
}

回溯算法的核心框架如下,只要在框架對應的位置加上對應的操作,即可將算法做選擇、撤銷選擇的過程完全展示出來,也許這就是套路框架的魅力所在:

for(charch='1';ch<=?'9';ch++){
Buttonb=newButton(r,c);
//做選擇
setNum(b,ch);
board[i][j]=ch;
//繼續(xù)窮舉下一個
backtrack(board,i,j+1);
//撤銷選擇
cancelNum(b);
board[i][j]='.';
}

以上思路就可以模擬出算法窮舉的過程:

37639858-c3bd-11ec-bce3-dac502259ad0.gif

--- EOF ---

審核編輯 :李倩

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 代碼
    +關注

    關注

    30

    文章

    4976

    瀏覽量

    74378
  • 回溯算法
    +關注

    關注

    0

    文章

    10

    瀏覽量

    6758

原文標題:搞懂回溯算法,我終于能做數(shù)獨了

文章出處:【微信號:TheAlgorithm,微信公眾號:算法與數(shù)據(jù)結構】歡迎添加關注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    【OFDR】實時感知、動態(tài)重構與歷史狀態(tài)回溯!昊衡科技-三維場重構軟件

    路徑映射三維螺旋路徑映射支持TCP實時數(shù)據(jù)傳輸,支持導入本地TXT數(shù)據(jù),對試驗過程進行回溯分析,方便后期數(shù)據(jù)復盤與優(yōu)化。數(shù)據(jù)回放功能界面從實時數(shù)據(jù)采集到三維場可視化,再
    的頭像 發(fā)表于 01-29 17:40 ?1479次閱讀
    【OFDR】實時感知、動態(tài)重構與歷史狀態(tài)<b class='flag-5'>回溯</b>!昊衡科技-三維場重構軟件

    回溯示波器的四次認知躍遷

    最近示波器圈熱鬧得有些“魔幻”,我抱著科普心態(tài)湊了幾次熱點,關于某款國產(chǎn)示波器的內(nèi)容卻接連被申退。倒也理解,行業(yè)風口下的爭議本就難免。但比起糾結單一產(chǎn)品,或許我們更該靜下心聊聊:這個被稱為電子
    的頭像 發(fā)表于 12-19 15:39 ?6822次閱讀
    <b class='flag-5'>回溯</b>示波器的四次認知躍遷

    何用FPGA控制ADV7513實現(xiàn)HDMI畫面顯示和音頻播放

    HDMI接口顯示使用DMT時序+TMDS編碼實現(xiàn)。當用FPGA控制HDMI的數(shù)據(jù)傳輸時,通常可以采用純RTL實現(xiàn)TMDS算法或者使用專門的HDMI芯片(如ADV7513)這兩種方案完成。本文主要是介紹如
    的頭像 發(fā)表于 12-02 11:05 ?7051次閱讀
    如<b class='flag-5'>何用</b>FPGA控制ADV7513實現(xiàn)HDMI畫面顯示和音頻播放

    8種常用的CRC算法分享

    CRC 計算單元可按所選擇的算法和參數(shù)配置來生成數(shù)據(jù)流的 CRC 碼。有些應用中,可利用 CRC 技術驗證數(shù)據(jù)的傳輸和存儲的完整性。 8 種常用的 CRC 算法,包括: CRC16_IBM
    發(fā)表于 11-13 07:25

    數(shù)智化光伏電站管理系統(tǒng)的“數(shù)智化”價值體現(xiàn)

    物聯(lián)網(wǎng)、大數(shù)據(jù)、人工智能、云計算、數(shù)字孿生等多種技術,通過技術融合與數(shù)據(jù)驅(qū)動,實現(xiàn)光伏電站效率躍升、成本優(yōu)化以及資產(chǎn)增值的核心價值。 數(shù)智化實現(xiàn)路徑主要是從技術架構、功能模塊等層面進行,依賴于技術架構與功
    的頭像 發(fā)表于 11-07 15:21 ?696次閱讀
    <b class='flag-5'>數(shù)</b>智化光伏電站管理系統(tǒng)的“<b class='flag-5'>數(shù)</b>智化”價值體現(xiàn)

    如何使用恢復算法實現(xiàn)開平方運算

    本文主要描述如何使用恢復算法實現(xiàn)開平方運算。 簡介 開平方的恢復算法其實與除法的恢復算法十分相似。首先我們假設X為輸入的操作數(shù)(它應該為正數(shù)),而他的平方根可以表示為Qn=0.q1
    發(fā)表于 10-24 13:33

    e203乘法運算結構及算法原理

    Booth算法 對于普通的乘法運算,以兩個8比特二進制數(shù)為例,可以寫為圖一所示的8個部分積之和: 同理,兩個32位二進制數(shù)相乘,在擴展符號位后,可以分為33個部分和之和。如果直接將33個部分和
    發(fā)表于 10-22 06:43

    基于FPGA的CLAHE圖像增強算法設計

    CLAHE圖像增強算法又稱為對比度有限的自適應直方圖均衡算法,其算法原理是通過有限的調(diào)整圖像局部對比度增強有效信號和抑制噪聲信號。
    的頭像 發(fā)表于 10-15 10:14 ?799次閱讀
    基于FPGA的CLAHE圖像增強<b class='flag-5'>算法</b>設計

    顯和集顯有什么區(qū)別?一篇搞懂!?

    選電腦時,“顯卡”是決定使用體驗的關鍵硬件。有人糾結“集顯夠不夠用”,有人擔心“顯太貴且笨重”。其實顯(獨立顯卡)和集顯(集成顯卡)沒有絕對的 “好壞”,只有“是否適配需求”:集顯適合日常辦公
    的頭像 發(fā)表于 09-19 16:09 ?8492次閱讀
    <b class='flag-5'>獨</b>顯和集顯有什么區(qū)別?一篇搞懂!?

    真隨機數(shù)和偽隨機數(shù)的區(qū)別

    隨機數(shù)在當前程序運行環(huán)境中是一種常用參數(shù),目前主要分為兩種,偽隨機數(shù)和真隨機數(shù),本期我們就來講一下二者的區(qū)別。
    的頭像 發(fā)表于 08-27 17:46 ?2888次閱讀

    生產(chǎn)線回溯追溯系統(tǒng)選型:中設智控方案如何破解行業(yè)痛點?

    中設智控產(chǎn)線回溯追溯方案,從硬件到功能,精準破解行業(yè)痛點,為電子制造、新能源等行業(yè)提供高效、可靠的生產(chǎn)管理工具,助力企業(yè)實現(xiàn)智能化生產(chǎn)升級,值得選型參考。
    的頭像 發(fā)表于 07-18 11:19 ?1181次閱讀
    生產(chǎn)線<b class='flag-5'>回溯</b>追溯系統(tǒng)選型:中設智控方案如何破解行業(yè)痛點?

    在友晶DE1-SOC開發(fā)板實現(xiàn)數(shù)謎題求解器

    數(shù)游戲是一種廣受歡迎的數(shù)學游戲。在其基本且被廣泛認可的形式中,數(shù)包含一個 9 × 9 的網(wǎng)格,其中某些方格已填入數(shù)字。該游戲的目的是通過填入剩余的方格
    的頭像 發(fā)表于 07-16 16:14 ?849次閱讀
    在友晶DE1-SOC開發(fā)板實現(xiàn)<b class='flag-5'>數(shù)</b><b class='flag-5'>獨</b>謎題求解器

    何用電容式的片式 CHIP LAN 網(wǎng)絡變壓器(電感)替代消費級傳統(tǒng)網(wǎng)絡變壓器,電氣原理圖是怎樣的?

    Hqst石門盈盛(華強盛)電子導讀:如何用電容式的片式 CHIP LAN 網(wǎng)絡變壓器(電感)替代消費級傳統(tǒng)網(wǎng)絡變壓器,電氣原理圖是怎樣的?這節(jié)將和大家一起做探討.....
    的頭像 發(fā)表于 07-13 11:01 ?2173次閱讀
    如<b class='flag-5'>何用</b>電容式的片式 CHIP LAN 網(wǎng)絡變壓器(電感)<b class='flag-5'>來</b>替代消費級傳統(tǒng)網(wǎng)絡變壓器,電氣原理圖是怎樣的?

    斬獲阿拉丁神燈獎兩大權威獎項,Yeelight易引領行業(yè)數(shù)智化升級

    近日,阿拉丁神燈獎獲獎名單公布,智能照明領導品牌Yeelight易,憑借其卓越的品牌創(chuàng)新力與產(chǎn)品技術實力,一舉奪得“2025阿拉丁神燈獎數(shù)智品牌獎”,旗下明星產(chǎn)品Yeelight智能筒射燈T4更
    的頭像 發(fā)表于 05-30 12:48 ?939次閱讀
    斬獲阿拉丁神燈獎兩大權威獎項,Yeelight易<b class='flag-5'>來</b>引領行業(yè)<b class='flag-5'>數(shù)</b>智化升級

    山東LP-SCADA故障回溯功能的好處

    關鍵字:LP-SCADA, LP-SCADA平臺 , LP-SCADA系統(tǒng), 軟件回溯功能,藍鵬測控 得益于本平臺毫秒級的采集延遲,本平臺除了具有普通監(jiān)控采集平臺的所有監(jiān)控功能外,還可用于產(chǎn)線、設備
    發(fā)表于 05-29 14:42
    镇赉县| 河西区| 宜黄县| 连江县| 开原市| 黄大仙区| 昌吉市| 六枝特区| 清丰县| 灯塔市| 塔城市| 江陵县| 宁河县| 屯昌县| 绥化市| 宜良县| 邳州市| 萨嘎县| 慈溪市| 绥阳县| 盐城市| 云南省| 海安县| 米易县| 普洱| 阳信县| 克拉玛依市| 温泉县| 莱州市| 广南县| 静乐县| 安阳市| 岐山县| 鄂伦春自治旗| 尖扎县| 岳西县| 台山市| 特克斯县| 五莲县| 大方县| 巴马|