哈密頓環解決貪吃蛇問題

2021-10-04 17:00:14 字數 1102 閱讀 1226

思路**於github上乙個專案:

snake

先給出哈密頓迴路的定義:哈密頓圖(哈密爾頓圖)(英語:hamiltonian graph,或traceable graph)是乙個無向圖,由天文學家哈密頓提出,由指定的起點前往指定的終點,途中經過所有其他節點且只經過一次。在圖論中是指含有哈密頓迴路的圖,閉合的哈密頓路徑稱作哈密頓迴路(hamiltonian cycle),含有圖中所有頂點的路徑稱作哈密頓路徑(hamiltonian path)。

首先很容易理解,如果我們希望貪吃蛇能從很小成長到填滿整個螢幕,那麼一定要吃掉所有出現的食物並避免蛇頭撞擊到蛇身。有一種最穩妥的執行策略是:將整個螢幕網格化,每乙個畫素點為乙個點,整個螢幕抽象為乙個圖,顯然這個圖存在哈密頓路徑。將哈密頓路徑上的點按次序編號,設蛇頭開始處為0,編號依次增加。則蛇頭只需一直沿著哈密頓路徑走就能訪問到圖中所有點,必定可以吃到食物,而且不會追尾。

然而這種策略顯然是冗長且乏味的,所以我們思考如何節約蛇行走的路程。仍然利用上文按次序編號的設定,我們同樣容易了解,如果蛇不想完全按哈密頓路徑行走,那麼只要它下乙個落腳點的編號在本該落腳的點的編號之後即可,這樣至少我們可以保證改變落腳點後,繼續沿著既定的哈密頓路徑行走,蛇頭能平安回到0點,進行下一輪哈密頓路徑的輪迴。

於是我們可以採用乙個不一定最優但稍有改進的策略:蛇頭依然依賴哈密頓路徑,但當它發現下乙個食物點的編號在蛇頭編號之後(兩點在當前同一哈密頓路徑內),且蛇頭只需變更一次方向即可直達食物點,那麼便不沿著原哈密頓路徑,而是選擇變向直達。之後如果再下乙個食物點還在蛇頭後則伺機抄近路,沒有近路則從蛇頭當前點繼續按照哈密頓路徑行走。

至於如何實現這種策略的更細緻的表述,由於我只是讀了很久原作者的思路,然後自己在腦子裡一直模擬,並沒有自己實現,所以當然沒有啦。不過初步想法是將整個哈密頓圖構造好後,就可以知道每個點上下左右是哪四個點。建立乙個一維陣列,每個陣列元素是乙個類物件,這個類有四個公有int資料成員,儲存其上下左右的點編號;還有乙個公有bool資料成員,表示該點是否被蛇的身軀覆蓋。這樣選擇抄近路時,就可以考慮四個方向的點,如果某個點在當前蛇頭和食物點之間,那麼變更到這個點。

可以看到這個策略和再之前文字表述的有些不同,當然啦,當我從程式設計角度考慮策略時往往和最初的思路有出入,而這種可落實的思路最後才能解決問題。

找時間搞一下這個程式吧。

哈密頓環求解 C 實現 回溯法

函式功能 求解哈密頓環 無向圖,有向圖請自改 問題,輸出全部不相同的環,即經過圖中每個結點並且只經過一次的可行解。作者 王宇虹 時間 2015年5月21日 13 23 00.000 編譯環境 dev c 5.8.3 include includeusing namespace std int n,m...

HDU 2181 哈密頓繞行世界問題

用dfs字典序搜尋即可,搜到末尾時回到原來的位置就是一條路徑,可以加乙個小剪枝,如果搜尋中經過了起始位置,可以剪枝 我把路徑打表儲存在陣列裡,防止有過多的重複輸入 include include include include includeusing namespace std const int...

HDU 2181 哈密頓繞行世界問題

由於資料量其實很小,直接dfs即可,細節見注釋 include include includeusing namespace std bool vis 21 int adj 21 3 cnt,tpath 20 start void dfs int k,int level return vis k 1...