搜索

BFS

864. 獲取所有鑰匙的最短路徑 )

BFS + 狀態(tài)壓縮

求最短路徑可以使用BFS,但本題不能使用一般的BFS來求解,因為我們在搜索的時候得記錄當(dāng)前已經(jīng)收集到的鑰匙,即收集狀態(tài),另外根據(jù)題意可知,與傳統(tǒng)的BFS不同,這里搜索是可以回退的。

根據(jù)題意可知,代表鑰匙和鎖的字母互為大小寫并按字母順序排列,因此我們可以用一個int類型的二進制數(shù)state來表示收集鑰匙的狀態(tài):

  • 若二進制中第k位為1,則表示字母序為k的鑰匙已被收集
  • 若二進制中第k位為0,則表示字母序為k的鑰匙未被收集

其中發(fā)鑰匙種類編號按小寫字母順序,從0開始進行先后劃分,a 對應(yīng)0, b 對應(yīng)1 .... ,例如當(dāng)前收集到的鑰匙為a, c,d,則對應(yīng)的二進制為1101

這樣,我們就可以通過位運算很容易更新鑰匙收集狀態(tài)鑰匙開鎖檢測

  • 鑰匙檢測: (state >> k) & 1,k表示編號為k的鑰匙,如果位運算結(jié)果為1則表示當(dāng)前已收集該鑰匙,結(jié)果為0 表示未收集該鑰匙。

  • 更新鑰匙收集狀態(tài):state = state | (1 << k),將statek位設(shè)置位1,表示已經(jīng)收集到該鑰匙。

有了記錄鑰匙收集狀態(tài)的方法,我們接下來進行BFS:

  1. 首先定義用來記錄路徑距離的數(shù)組dist,與傳統(tǒng)的BFS不同,我們除了要表示當(dāng)前位置的坐標(biāo)(i, j)外,我們還需要表示當(dāng)前位置的鑰匙收集狀態(tài),因為每次經(jīng)過同一個位置時可以有多個鑰匙收集狀態(tài)。我們用一個三維數(shù)組dist[i][j][s]來記錄在(i, j)位置且鑰匙收集狀態(tài)為s時的最短路徑距離。將起點,鑰匙手機狀態(tài)為0的dist初始化為0,其他初始化為無窮大。
  2. 遍歷棋盤,找到起點位置,初始化起點的dist為0,然后將起點信息加入隊列,隊列維護的是三元組{i, j , s}的狀態(tài)。
  3. 進行四聯(lián)通方向遍歷
    • 如果遇到墻,該遍歷方向違法,continue
    • 如果遇到鎖,且當(dāng)前收集的鑰匙無法開始,改遍歷方向違法, continue
    • 如果是鑰匙且未收集,更新鑰匙收集狀態(tài)ns
    • 如果dsit[x][y][s] + 1 > dsit[nx][ny][ns],說明改遍歷方向不是最短路徑,不符合題意,continue
    • 否則,我們更新dsit[nx][ny][ns] = dsit[x][y][s] + 1 并將{nx, ny, ns}加入隊列
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容