馬踏棋盤及其優化

2021-08-29 18:21:18 字數 3149 閱讀 2871

在8*8的西洋棋棋盤中的任何乙個位置,放置乙個馬(棋子),使其按照馬在西洋棋中的規則(走日)進行移動,求其中的乙個解。

這其實是乙個深度優先搜尋的問題,深度優先搜尋一般使用遞迴實現,在這裡,為了學習,使用我們更不熟悉的棧來操作。

1.給定乙個起點,將起點入棧,步數step=1。

2.在map陣列中的該位置的值賦為step;step++; 

3.根據上圖,按照0~7的順序試探下乙個點:令direction=0,若下乙個點位置合法,則下乙個點入棧,再執行第3步;若下乙個點位置不合法,試探下乙個方向,即direction++。 4.若試探第7個方向direction==7,下乙個點仍然不合法,則該點出棧,將棧頂的direction++,且將當前位置設定為棧頂的位置。 5.重複第3,4,直到步數step=64(棋盤已經被填滿)或者,棧為空(沒有解)(當然,一定會存在解)

#include #include #define size 8

typedef structpoint;

typedef struct nodepathnode;

typedef structstack_path;

int minindex(int p);//求乙個陣列的最小值的下標

stack_path *init_stack(void);//初始化乙個棧

void push(stack_path *s,point p);//入棧

void pop(stack_path *s,point *p);//出棧

int isempty(stack_path *s);//判空

int isqualified(point p);//判斷某乙個點是否合法

void go(int x,int y);//輸入起點

void print();//輸出路徑

point gettop(stack_path *s);//獲得棧頂元素

point nextpos(point curpos);//生成下乙個點

int map[size][size];//記錄map[x][y]是第幾步

int main(void);

stack_path *init_stack(void)

void push(stack_path *s,point p)

void pop(stack_path *s,point *p)

int isempty(stack_path *s)

int isqualified(point p)

point nextpos(point curpos);

point nextpos;

nextpos.x=curpos.x+next[curpos.direction][0];

nextpos.y=curpos.y+next[curpos.direction][1];

nextpos.direction=0;

return nextpos;

}void go(int x,int y)

else

++path->top->next->data.direction;//將棧頂的試探次數加一

}curpos=gettop(path);//將當前位置設定為棧頂

}return ;

}

最壞的情況下,每乙個點都會回溯最大次數,也就是說每個點都會走8次,那麼,總共走了8的64次方次,效率十分低下,主要的時間花費在了回溯上,因次,可以通過減少回溯次數來提高效率。

每次不按照順時針的方向進行試探,優先試探可以到達的點的個數更少的點,若下乙個點只有乙個點可以到達,那麼若行不通,一次試探後就可以回溯,這樣就減少了回溯的次數。

當然,如果要求處所有的解,上述方法並不能得到優化,但是若要求出乙個解,那會大大的提高效率。

1.首先更新資料型別

typedef structpoint;
這裡,新加入了乙個first陣列,first陣列用來儲存方向,按照下乙個可到達點的個數公升序儲存。順序訪問first,試探的方向就不會是順時針,而是按照下乙個點的可到達點的個數公升序排列的。 direction在這裡可以理解成試探的次數。

2.新加入幾個函式

宣告

int getnum(point curpos,int next[2]);//計算乙個點可以到達其他點的個數

void setfirst(point *curpos);//計算first陣列的值

int minindex(int p);//找出陣列最小值的下標

實現

int getnum(point curpos,int next[2])

//找到nextpos可到達的點最少的方向,賦值給first

for(int i=0;ifirst[i]=minindex(num);

num[minindex(num)]+=9;//最小值存過之後,加個9讓它變成較大的值

}return ;

}int minindex(int p)

return min;

}

4.既然不按順時針方向試探,就要修改nextpos()函式

point nextpos(point curpos);

point nextpos;

//first裡儲存了該點到下乙個點的方向次序,derection代表試探次數

nextpos.x=curpos.x+next[curpos.first[curpos.direction]][0];

nextpos.y=curpos.y+next[curpos.first[curpos.direction]][1];

nextpos.direction=0;

return nextpos;

}

按照衝0~7的順序訪問first陣列,first陣列中儲存了方向

5.修改go()函式,在壓入棧之前,要給first陣列賦值

void go(int x,int y)

else

++path->top->next->data.direction;//將棧頂的試探次數加一

}curpos=gettop(path);//將當前位置設定為棧頂

}return ;

}

馬踏棋盤python 馬踏棋盤python實現

import collections import random class checkerboard object 初始化棋盤 def init self,len self.len len self.position has gone set def init checkerboard self ...

馬踏棋盤的貪心優化

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

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

問題描述 曾經用簡單的深度優先搜尋方法 遞迴的形式對馬踏棋盤進行搜尋,執行效率不甚理想。部落格見馬踏棋盤之遞迴實現 所以現在用貪心演算法將其優化了一下。問題解析 主要的思想沒有變,還是用深度優先搜尋,只是在選下乙個結點的時候做了貪心演算法優化,其思路如下 從起始點開始,根據 馬 的走法,它的下一步的...