馬踏棋盤之貪心演算法優化

2021-06-27 07:47:53 字數 2150 閱讀 9360

問題描述:

曾經用簡單的深度優先搜尋方法、遞迴的形式對馬踏棋盤進行搜尋,執行效率不甚理想。(部落格見馬踏棋盤之遞迴實現)。

所以現在用貪心演算法將其優化了一下。

問題解析:

主要的思想沒有變,還是用深度優先搜尋,只是在選下乙個結點的時候做了貪心演算法優化,其思路如下:

從起始點開始,根據「馬」的走法,它的下一步的可選擇數是有0—8個的。

我們知道,當下一步的可選擇數為0的時候,進行回溯。當下一步的可選擇數有1個的時候,我們直接取那一步就行了。

但是如果下一步的可選擇數有多個的時候呢?

但其實我們怎麼選下一步,對搜尋的效率影響是非常大的!

先介紹一下「貪心演算法」。百科裡面的定義是:貪心演算法(又稱貪婪演算法),是指在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,他所做出的僅是在某種意義上的區域性最優解。

它只考慮區域性的最優,從而讓總體也最優。就我們這個馬踏棋盤來說,我們每走一步都取最優的那個選擇,從而讓整體的演算法也最優。

但是我們選擇下一步的時候(假設有a、b、c、d四個點可以選擇),怎樣選才算是最優呢?

答案是:哪乙個點的下一步少,就選哪乙個。

我們選擇a、b、c、d之中的某乙個點作為下一步,選哪個比較好,就看哪個點的後續下一步比較少。例如:馬走到a點後的下一步有3個選擇;而b的下一步有2個;c有1個,d有2個。那麼我們的最優選擇是:c點!

為什麼要這樣選呢?網上的解釋是:「選擇最難走的路,才能走的遠」嗚。。。好像太抽象了。

話以後可能會很難遍歷到它。

甚至極端一點的情況是,如果現在不遍歷它,以後都遍歷不到了。遍歷不成功的時候只能回溯,一直回溯到此刻的點,然後選了c點以後才能完成,這就浪費了大量的時間。

下面放出所有**,詳細的解釋後面再補上:

#include#include#define h 3     // 代表對下一步的排序只取出最小的2個,而不是對8個都排序,這樣可以節省很多時間

int fx[8] = , fy[8] = , f[8] = ;

// fx 和 fy 表示馬在二維的八個方向,給二維座標x和y用;f表示一維的八個方向,給陣列a用。

int dep = 1; // dep 為遞迴的深度,代表在當前位置馬已經走了多少步

int count, z = 0, zz = 0; // count 表示目標要多少種解法,而 z 記錄當前算出了多少種解法,zz 記錄在運算中回溯的次數

int out[100001][8][8], f[8], a[64]; // out 記錄所有的遍歷路徑,a 用一維陣列記錄 8*8 棋盤中馬的遍歷路徑

// 輸入起始座標,對存放遍歷路徑的陣列a進行初始化

int prepare()

// sortint() 函式對點 n 的下一步進行「後續下一步可選擇數」的排序,結果儲存在 b 裡面

// c 表示前驅結點在結點 n 的哪個位置。

void sorting(int b[64][h], int n, int c)

} }

b[n][0] = -1;

for(i=1; i-1 && f[j]= 0)

{ if(b[n][0]!=-1 && b[n][0]

執行結果如下(vc6.0、32位win8系統 + i7-3612qm處理器,如果使用vs時間會長一點):

測試了一下:十萬條路徑,耗時1秒多!!!效率比普通的深度優先搜尋不知道高了多少倍!

備註:以上**是四個月前寫的,現在才整理出來。打擊很大,當初不注意**的格式和備註,現在看自己寫的**看到頭暈腦炸,自食其果!以後必須注重寫**的風格,注意寫上必須的備註,連自己寫的**的看不懂,真真可笑。一直看了好久終於看明白各個函式 各個變數的作用了,也改了一些格式,寫了一些備註,到現在正的看不下去了。先把文章放出來,緩一陣再回來完善。

貪心演算法 馬踏棋盤(C)

貪心演算法 又稱貪婪演算法 是指,在對 問題求解 時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,他所做出的僅是在某種意義上的區域性 最優解。貪心演算法不是對所有問題都能得到整體 最優解,但對範圍相當廣泛的許多問題他能產生整體最優解或者是整體最優解的近似解。貪婪演算法是一種改進...

馬踏棋盤的貪心演算法

問題描述 馬的遍歷問題。在 方格的棋盤上,從任意指定方格出發,為馬尋找一條走遍棋盤每一格並且只經過一次的一條路徑。初步設計 首先這是乙個搜尋問題,運用深度優先搜尋進行求解。演算法如下 輸入初始位置座標x,y 步驟 c 如果c 64輸出乙個解,返回上一步驟c x,y c 計算 x,y 的八個方位的子結...

馬踏棋盤的貪心優化

資料結構上機時發現有乙個優化馬踏棋盤的方法。僅適用於優化求解乙個 或少數 對於求所有解時間不變。即dfs查詢路徑時優先選擇孫節點少的子節點。下面附上 include include include include using namespace std struct node int map 10 ...