Python----DFS---騎士周游問題


這篇文章將會將一個數據結構與算法中一個很經典很重要的概念——深度優先搜索(Depth-First-Search:DFS)。。。。。。。。。(你他喵不是在標題里說了嗎?)

好吧,DFS的精髓我其實也還沒有弄的特別懂,估計得多用用才能理解更深吧。

!!!敲黑板!!!DFS的關鍵是遞歸,遞歸是真好用!!!

 


深度優先搜索(DFS)

什么是DFS呢,秉着能動手就絕不吵吵的原則,直接給出網上大神的博文鏈接:http://www.cnblogs.com/skywang12345/p/3711483.html

好吧,其實這種鏈接你自己都能百度到的。我就放這里做個參考,我的主要目的還是要講一下騎士周游問題。

騎士周游問題

騎士周游問題的主要內容是什么呢?不是廢話,直接上網址:http://blog.fishc.com/2554.html,這個頁面對DFS問題說明的非常清楚。作者是小甲魚大神,我在B站看的就是他的數據結構課程,不時的開個車差點閃了我的腰。

特喵的,不是說好的不說廢話嗎?(我錯了,好吧)

好吧,直接上代碼:

import datetime
from enum  import Enum

class Size(Enum):
    X = 8

start = datetime.datetime.now()
chess = [[0 for i in range(Size.X.value)]for j in range(Size.X.value)]

def nextXY(x, y, position):
    global chess
    if position==0 and x-2>=0 and y-1>=0 and chess[x-2][y-1]==0:
        return [1, x-2, y-1]
    elif position==1 and x-2>=0 and y+1<=Size.X.value-1 and chess[x-2][y+1]==0:
        return [1, x-2, y+1]
    elif position==2 and x-1>=0 and y-2>=0 and chess[x-1][y-2]==0:
        return [1, x-1, y-2]
    elif position==3 and x-1>=0 and y+2<=Size.X.value-1 and chess[x-1][y+2]==0:
        return [1, x-1, y+2]
    elif position==4 and x+1<=Size.X.value-1 and y-2>=0 and chess[x+1][y-2]==0:
        return [1, x+1, y-2]
    elif position==5 and x+1<=Size.X.value-1 and y+2<=Size.X.value-1 and chess[x+1][y+2]==0:
        return [1, x+1, y+2]
    elif position==6 and x+2<=Size.X.value-1 and y-1>=0 and chess[x+2][y-1]==0:
        return [1, x+2, y-1]
    elif position==7 and x+2<=Size.X.value-1 and y+1<=Size.X.value-1 and chess[x+2][y+1]==0:
        return [1, x+2, y+1]
    else:
        return [0, x, y]

def TravelChessBoard(x, y, tag):
    global chess
    chess[x][y] = tag
    if tag == Size.X.value**2:
        for i in chess:
            print(i)
        return "OK"
    f = 0
    for i in range(8):
        flag = nextXY(x, y, i)
        if flag[0]:
            statues = TravelChessBoard(flag[1], flag[2], tag+1)
            if statues=="OK":
                return "OK"
            f += 1
        else:
            f += 1
    if f == 8:
        chess[x][y] = 0


print(TravelChessBoard(2, 0, 1))
print(datetime.datetime.now() - start)

 

 整單代碼一共可以分為三個部分:變量准備部分,位置判斷部分,循環遞歸部分

1.變量准備部分:

    • 定義了一個size枚舉類,這是用於實現C語言中宏定義的功能特意定義的,當然你用別的方法也行,主要就是為了方便改變棋盤的規模。
    • 定義了一個棋盤變量,是一個二維矩陣,全部元素初始化為0。也就是問題中的棋盤

2.位置判斷部分:

    • 函數有三個參數,分別是坐標x, y和位置position, 這個位置position先來解釋一下,如下圖[1]所示,在國際象棋中,按照馬的走法(馬走日)對於任何一個位置,馬能走的地方一共有8個位置,每一個位置對應的坐標變換不一樣,這里的position對應的就是8種坐標變換方式。(x, y)就是馬當前所處的位置坐標
    • 返回的參數為一個列表,列表中包含三個元素,第一個元素表示8個位置是否存在滿足條件的下一個位置,若存在,則第二、三兩個元素返回新位置的坐標,若不存在,返回原始坐標
    • 判斷的條件主要就是同時滿足兩個方面:坐標不能出界,坐標對應的位置未曾走過(位置上的值為0),兩者都滿足即存在滿足條件的下一個位置
  • 循環遞歸函數:
 1 def TravelChessBoard(x, y, tag):
 2     global chess
 3     chess[x][y] = tag
 4     if tag == Size.X.value**2:
 5         for i in chess:
 6             print(i)
 7         return "OK"
 8     f = 0
 9     for i in range(8):
10         flag = nextXY(x, y, i)
11         if flag[0]:
12             statues = TravelChessBoard(flag[1], flag[2], tag+1)
13             if statues=="OK":
14                 return "OK"
15             f += 1
16         else:
17             f += 1
18     if f == 8:
19         chess[x][y] = 0
    • 傳進來的參數為當前馬所在的位置(x, y),以及當前走的是第幾步(tag的值)
    • 3行,chess[x][y] = tag, 另當前位置的值等於當前的步數,未到達的地方則為0,以此判斷一個位置是否到達過
    • 4-6行,如果步數等於棋盤的總格數(這里默認為方盤),則將棋盤打印出來,返回”OK“狀態,告訴上一層遞歸已經尋找到解了,無需再作其它搜索了
    • 8行,定義一個過程變量f = 0, 作用稍后會講到
    • 9-17行,對馬的當前位置的下8個位置進行遍歷,對於每一個位置,如果存在下個符合條件的位置則進入遞歸,將符合條件的下一個位置作為當前位置傳入遞歸函數中,步數加1。對8個位置遍歷,每次出現一個不符合條件的位置則f的值就加一。
    • 18-19行,當8個位置全部遍歷完,沒有一個符合條件的位置,那么此時f = 8,說明當前位置是不符合條件,那么就將當前位置的值重新置為0。
    • 再說第12-15行,當深層的遍歷找不到合適的位置時,遞歸會退回到前一層,這說明前一層的當前位置也不符合條件,那么f的值就必須加1,然后繼續遍歷前一層的下一個位置,以此類推。
    • 最后再說13-14行,當已經找到並打印出符合條件的路徑后,程序飯后”OK“狀態,此時程序的遞歸就會從最后一層不斷往前一層返回,為了加快程序結束的速度,就不繼續進行剩下的遍歷,每一層遞歸都直接返回可以了。如果不直接返回的話,程序會將所有的情況都遍歷完再返回,這樣時間就會非常非常非常長。YOU CAN HAVE A TRY !!!

到此這個程序也差不多講完了,我覺得只要理解遞歸了,這個程序應該不難理解。 


連續幾天都在用遞歸,對遞歸的運用也越來越熟練,確實非常好用,真誠地希望這篇文章對你有幫助。

願各位學業有成!!!

 

 

 

[1] 圖拷貝自http://blog.fishc.com/2554.html,感謝魚C工作室。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM