Python3趣味系列題9-------一筆畫完

0.png

一、問題描述

一筆畫完就是從起始網格開始,也就是下圖中錦鯉喵所在的網格,用一筆劃過所有可以走(灰底)的網格,不能遺漏,也不能重複。下圖是微信小遊戲一筆畫完第1350關的題目:

image

image

二、解題思路

利用 DFS(深度優先搜索)和BFS(廣度優先搜索) 算法找到所有的路徑,利用基於多線程實現的計時器展示尋找路徑所用的時間,最終圖示所有的解。簡單說下兩個算法的區別:

  • DFS(Depth First Search) 也就是深度優先搜索,也就是從起始網格開始,只要是還有可以去的網格,就一直走下去,直到走不通爲止,然後再回溯到最近的一次選擇,再往下走,直到遍歷完所有的路徑。

  • BFS(Breadth First Search) 也就是廣度(寬度)優先搜索,也就是從起始網格開始,首先搜索與之相鄰的網格,然後在搜索與這些網格相鄰的網格。換句話說,就是逐漸的向周圍擴散搜索。

兩者利用Python實現的區別:DFS一般利用遞歸實現,因爲涉及到回溯,實現較爲複雜。因爲Python中對遞歸函數有調用次數的限制,因此需要自己實現尾遞歸優化。對於BFS而言,實現比較簡單,但是因爲需要保存當前的所有路徑,當路徑較多時,佔用的內存空間較大,因此需要刪除一些不合理的路徑。

從運行時間上而言,獲取一條路徑優先選擇DFS,獲取所有路徑BFS好於DFS。但是當可走的網格數較大時,優先選擇DFS,因爲BFS可能導致內存負載超重。

image

三、Python3實現

利用numpy的數組形式來描述問題,也就是不同性質的網格給定不同的數值,便於繪圖。需要根據謎題題面,自定義輸入數組的維數,以及起始網格的索引,不可走網格的索引。根據這些設置,生成相應的二維數組,並利用matplotlib繪製出來。下面以上面的謎題爲例,需要進行下面的設置:

# 豎直、水平方向網格的個數
Map_Height = 9
Map_Width = 7
# 起始網格和不能經過的網格的索引
Start_Index = [1, 0]
Stone_Index = [[0, 3], [0, 6], [1, 6], [2, 6], [3, 1], [7, 1], [8, 3], [8, 5], [8, 6]]

image
上圖爲第1350關的題面的示意圖
image
上圖是根據題面信息繪製的圖

下面說一下對路徑合理性的判斷,對於一筆畫完的問題,當走過的網格和不能走的網格,把剩下可以走的網格分爲不連通的兩部分時,就可判斷當前的路徑是不合理的,也就沒有在這個路徑上繼續往下搜索的意義。下圖顯示了加入路徑合理性判斷後的情況對比:
image
關於兩種算法的實現,尾遞歸的優化以及基於多線程的計時器的實現,參見代碼註釋。
考慮到手動輸入題面信息的繁瑣,還實現了自動讀取謎題照片。當然對照片的質量要求較高(屏幕截圖可以(下圖上,第1350關的題面截圖),相機拍攝(下圖下)會有問題)。

image
image
image
三、結果圖示
image
image

第1350關一共有108條路徑解法,上圖上展示了基於BFS方法的第16個,上圖下展示基於DFS方法的第108個。獲取所有路徑前者耗時大約105秒,後者大約186秒。

image
上圖是根據DFS,獲取的一條路徑以及所用時間。
image
image
上圖上是根據題面截圖自動讀取出來的結果,上圖下是添加路徑後的結果。因爲調用的是DFS方法,所以得到的結果和上圖是一樣的。

點擊獲得更多趣味謎題。歡迎Follow,感謝Star!!! 掃描關注微信公衆號pythonfan,獲取更多。
image

image