讀古今文學網 > 算法神探:一部谷歌首席工程師寫的CS小說 > 25 用優先隊列來解鎖 >

25 用優先隊列來解鎖

一小撥混混兒正等在Frank的辦公室門口。他們本想混進去,但老遠就被Frank認出來了。他們中的一個坐在長凳上,一邊裝作讀報紙,一邊來來回回打量著整條街。另外三個站在角落旁,正大聲討論最近的體育賽事。Frank走近一聽才發現他們在假裝聊天:其中一人大聲抱怨皇家馬球比賽的裁判,另一個在說即將到來的賽馬內幕,剩下那個只會時不時地念叨一聲「體育比賽」。

只有那個探子成功隱蔽了自己。她等在街對面,隨意地靠在牆上。要不是曾經追捕過她,Frank大概就徹底忽略掉她了。她很厲害,或者說,主要是那些小混混兒太差勁了。

Frank沒有停下來,接著拐進了小巷子。那群Vinettee集團的小混混兒們正等著他,所以他沒法回辦公室。略作思考後,他去了一間警察安全屋。離得不遠,也很久沒有人用過了。幸運的話,他沒準還能想起門鎖密碼。

離安全屋還剩半個街區的時候,Frank聽見他身後傳來了喊叫和重重的腳步聲。那個探子一定是通知他們了。

「Frank!」一個強壯的惡棍喊道,「我們只是想和你聊一聊。」

其他人都笑了起來,讓人覺得這句話好像合情合理,難以懷疑他們的本來動機。Frank拔腿就跑,身後的腳步聲也跟了上來。

Frank突然向左急轉彎,跑進了一條狹窄的小巷。Frank對這裡非常熟悉,他一定要想辦法甩掉這些惡棍。他現在必須盡快找到安全屋,因為安全屋門上有把密碼鎖,所以要進屋需要花點時間,除非他能在第一次就試對密碼。

Frank從小巷走到了Flag街上,快速轉彎,進入角落裡的商店中。他假裝在兒童服裝貨架周圍轉悠著,同時還向窗外看著。在這個位置能夠很好地對商店外邊進行監視。

沒過一會,惡棍們就蜂擁到了街上,胡亂地到處看。間諜緊跟其後並發佈命令。她將惡棍分成兩組,分別沿著街道的兩個方向繼續尋找,而她則在胡同的口等著。

Frank一刻也不敢停留。他抓緊時間從商店出來,然後朝著另一扇門走去,這扇門通向一個小巷子。間諜就在Frank身邊十步遠的地方,背對著他。Frank又悄悄地從巷子裡撤了回來,向安全屋走去。假如他足夠走運,那些惡棍沒想到去向店員打聽什麼的話,他便能爭取到更多的時間了。

在安全屋的門口,Frank嘗試著解鎖。他先嘗試1-1-1。不可否認,這是一個簡單的密碼。鎖沒能打開。

Frank咒罵起來,從他上次到過這裡後,一定有人更換過密碼。Frank現在面臨兩種選擇,一種是繼續嘗試密碼開鎖,但是這可能需要花費很長時間;第二種是去找另一個地方藏身。但他再也想不到另一個安全並且惡棍找不到的地方了,於是他又轉身繼續面對這把鎖。

由於時間非常緊張,Frank需要提高效率。密碼由三個數字組成,每個數字可能是1~20中的任意一個,所以他面對8000種可能的組合。Frank此刻沒有時間進行廣度優先搜索或深度優先搜索。相反,他必須依靠有限的搜索和一些猜測來破解密碼。此刻,他必須相信自己的直覺。Frank從口袋裡取出記錄優先隊列的紙,擦乾淨,開始把嘗試的每一種組合記下。他為每一個密碼組都添加了一個優先級——是他對每組密碼可能性的直覺。他開始嘗試警察們的常用組合:

1-2-3

1-1-2

1-3-5

Frank將這三個組合的優先級都設為10。

然後,他開始嘗試由三個重複數字組成的三元組。如果密碼曾經是1-1-1,為什麼不使用2-2-2?安全屋很少被使用,所以它很可能只使用簡單密碼。他列出了19個未嘗試過的三元組,並賦予優先級5,現在優先隊列中已有22個待嘗試的密碼。

接下來,他通過負責安全屋警察的生日增加了六個可能的密碼組,並賦予優先級8。他還添加了此時能記起的其他警察生日的密碼組,並賦予優先級2。

最後,他添加了單詞RUN並賦予優先級1。他知道,如果試到該項,就是時候放棄了,他必須找到另一個地方藏身。

現在優先隊列中有32個密碼組。需要把每個密碼組都嘗試一遍。在頂部是最高優先級的密碼組:1-2-3。Frank試了一下,鎖並沒有開。

他大罵一聲並把剛才嘗試過的密碼組從優先隊列中刪除,此時新的最高優先級的密碼組便會自動出現在優先隊列的頂部。

在嘗試下一個密碼組之前,Frank突然有個想法。他們會把舊密碼做一些變化後再使用嗎?他知道很多警察使用一個組合作為他們的儲物櫃的密碼,並把這個密碼顛倒一下作為行李箱的密碼。負責安全屋的警察是否也會這樣做?Frank把3-2-1這個密碼組添加到他的優先隊列的底部,並賦予優先級9。

1-1-2和1-3-5都不正確,所有優先級為10的密碼組都嘗試過了。Frank把它們顛倒後的密碼組2-1-1和5-3-1也添加到優先隊列的底部,並賦予優先級9。

Frank從優先隊列頂部取出下一個優先級最高的密碼組3-2-1。這是他剛剛添加的顛倒後的密碼組之一。這正是優先隊列的魔力,無論你以什麼樣的先後順序去添加密碼組,你總能得到隊列當中優先級最高的那個。

鎖開了,密碼是5-3-1,密碼組中優先級為9的一個。Frank緩緩地歎了一口氣,瞥了一眼,沒有Vinettee集團的跡象。他現在安全了。

警用算法導論:數據結構和搜索

節選自Drecker教授講義

正如我們在整個學期的講座中所討論的,我們使用的數據結構可以影響算法的實現方式和效率。在深度優先搜索和廣度優先搜索的講義中,我們研究了棧和隊列之間的差異,以及它們是如何影響搜索順序的。在最佳優先搜索中,使用優先隊列是數據結構影響算法效率的另一個很好的例子。

從概念上說,最佳優先搜索類似於廣度優先搜索和深度優先搜索——在算法的每一步,都會選擇一個新狀態來進行探索。它們之間最關鍵的區別在於如何安排新產生的狀態的探索次序。使用優先隊列可以讓我們每次都更有效地挑選出最接近目標解的狀態。最佳優先搜索與優先隊列是一對完美的組合,是一組極其高效的「數據結構+算法」的範例。