A*算法python編寫迷宮問題


題目

假設一個探險家被困在了地底的迷宮之中,要從當前位置開始找到一條通往迷宮出口的路徑。迷宮可以用一個二維矩陣組成,有的部分是牆,有的部分是路。迷宮之中有的路上還有門,每扇門都在迷宮的某個地方有與之匹配的鑰匙,只有先拿到鑰匙才能打開門。請設計一個算法,幫助探險家找到脫困的最短路徑。如前所述,迷宮是通過一個二維矩陣表示的,每個元素的值的含義如下 0-牆,1-路,2-探險家的起始位置,3-迷宮的出口,大寫字母-門,小寫字母-對應大寫字母所代表的門的鑰匙

輸入描述:

迷宮的地圖,用二維矩陣表示。第一行是表示矩陣的行數和列數M和N
后面的M行是矩陣的數據,每一行對應與矩陣的一行(中間沒有空格)。M和N都不超過100, 門不超過10扇。

輸出描述:

路徑的長度,是一個整數
 
        
示例1
 
        

輸入

復制
5 5
02111
01a0A
01003
01001
01111

輸出

復制
7


解題思路:
這道題為了練習A*算法。題目里加了鑰匙和門,我按照 一把鑰匙對一扇門,一定要找一把鑰匙過一扇門,的順序寫的。
最后的思路就是 從起點找 到第一把鑰匙的路,然后找從第一把鑰匙到第一扇門的路,然后找第一扇門到第二把鑰匙的路依次類推。
把每一次尋路,都用A*算法來求解。
#讀取輸入數據
hh=input()
# hh='5 5 021b1 01A0B 01003 0a000 01111'

# hh='5 5 02111 01a0A 01003 01001 01111'
hh0=hh.split()
M=int(hh0[0])
N=int(hh0[1])

maxz=[]
for x in range(int(M)):
    maxz.append(list(hh0[x+2]))
#-------------------------------------------------
# M=5
# N=5
# maxz=[['0','2','1','1','1'],
#       ['0','1','a','0','A'],
#       ['0','1','0','0','3'],
#       ['0','1','0','0','1'],
#       ['0','1','1','1','1']]
#-------------------------------------------------
#數據初始化

start0=[]
end0=[]

#提取所有帶字母的鑰匙和門
dicta=[]
dictb=[]

for x in range(M):
    for y in range(N):
        if maxz[x][y]=='2':
            start0=[x,y]
        elif maxz[x][y]=='3':
            end0=[x,y]
        elif 96 < ord(maxz[x][y]) < 123 or 64 < ord(maxz[x][y]) < 91:
            dicta.append([maxz[x][y],x,y])

#按鑰匙字母排序
dicta.sort(key=lambda x:x[0])
lena=len(dicta)
# print(dicta)
lena=len(dicta)

#轉換成鑰匙和門的組合
for x in range(lena//2):
    dictb.append(dicta[(lena // 2) + x][1:3])
    dictb.append(dicta[x][1:3])
#---------------------------------------------------------

#計算 G,H,F,P值   G為當前點到起點的距離,H為當前點到終點的距離,F為G+H,P為來源點
def distance(Node_current7,yuandian,start8,end8):
    P=yuandian
    G=abs(Node_current7[0]-start8[0])+abs(Node_current7[1]-start8[1])
    H=abs(Node_current7[0]-end8[0])+abs(Node_current7[1]-end8[1])
    F=G+H
    return [F,P]

#查找周圍的臨接點
def findNeighbors(nc,maxz9,Node_start7, Node_end7):
    open_list9=[]

    if nc[0]>0:   #取上面的點
        if maxz9[nc[0]-1][nc[1]]!='0':
            open_list9.append([nc[0]-1,nc[1],distance([nc[0]-1,nc[1]],nc[0:2],Node_start7, Node_end7)])
    if nc[0]<M-1:  #取下面的點
        if maxz9[nc[0]+1][nc[1]]!='0':
            open_list9.append([nc[0]+1,nc[1],distance([nc[0]+1,nc[1]],nc[0:2],Node_start7, Node_end7)])
    if nc[1]>0:   #取左面的點
        if maxz9[nc[0]][nc[1]-1]!='0':
            open_list9.append([nc[0],nc[1]-1,distance([nc[0],nc[1]-1],nc[0:2],Node_start7, Node_end7)])
    if nc[1]<(N-1):  #取右面的點
        if maxz9[nc[0]][nc[1]+1]!='0':
            open_list9.append([nc[0],nc[1]+1,distance([nc[0],nc[1]+1],nc[0:2],Node_start7, Node_end7)])
    return open_list9

#從openlist找到F值最小
def findMinNode(openlist_temp):

    y1=openlist_temp[0]
    for x1 in openlist_temp:
        if y1[2][0]>x1[2][0]:
            y1=x1
    return y1

# A*搜索
def aStarSearch(Node_start, Node_end,maxz0):
    OpenList=[]
    CloseList=[]
    Node_current=[]
    List_neighbors=[]
    term_result=[]

#     把起點加入 open list
    OpenList.append([Node_start[0], Node_start[1], [0, [-1,-1]]])
#     主循環,每一輪檢查一個當前方格節點
    while len(OpenList)>0:
        # 在OpenList中查找 F值最小的節點作為當前方格節點
        Node_current = findMinNode(OpenList)
        # 當前方格節點從open list中移除
        OpenList.remove(Node_current)
        # 當前方格節點進入 close list
        CloseList.append(Node_current)

        # 找到所有鄰近節點
        List_neighbors = findNeighbors(Node_current,maxz0,Node_start, Node_end)
        for x in List_neighbors:
            if (x not in OpenList) & (x not in CloseList):
                #鄰近節點不在OpenList,CloseList中,標記父親、G、H、F,並放入OpenList
                OpenList.append(x)

       # 如果終點在OpenList中,直接返回路徑
        for x in OpenList:
            if Node_end==x[0:2]:   #如果找到
                term_result.append(x[0:2])
                temp0 = x
                while Node_start != temp0[0:2]:
                    for z in CloseList:
                        if temp0[2][1] == z[0:2]:
                            temp0 = z
                            term_result.append(temp0[0:2])
                            break
                term_result.pop()
                # print(term_result[::-1])
                return len(term_result)

    # OpenList用盡,仍然找不到終點,說明終點不可到達,返回空
    return None


dictb.insert (0,start0)  #把起點添加進頭部去
dictb.append(end0)  #把終點添加進去
sum0=0

for y in range(len(dictb)-1):
    sum0 +=aStarSearch(dictb[y],dictb[y+1],maxz)

print(sum0)

  

測試幾個問題都沒啥事,最后困難的上線怎么也通不過,無語了。多半是輸入的格式理解有誤吧。堅信自己的代碼沒問題。
網友們如果看出了我的錯誤請不吝指正!
 


免責聲明!

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



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