07.30 什麼是聰明!從“螞蟻爬杆”問題,一切明瞭

有一根27釐米的細木杆,在第3釐米、7釐米、11釐米、18釐米、23釐米這五個位置上各有一隻螞蟻。木杆很細,不能同時通過兩隻螞蟻。開始時,螞蟻的頭朝左還是朝右是任意的,它們只會朝前走或調頭,但不會後退。當任意兩隻螞蟻碰頭時,兩隻螞蟻會同時調頭朝反方向走。假設螞蟻們每秒鐘可以走一釐米的距離。編寫程序,求所有螞蟻都離開木杆的最小時間和最大時間。

什麼是聰明!從“螞蟻爬杆”問題,一切明瞭

解決這個問題最簡單的方法便是暴力破解。所謂的暴力破解,就是遍歷所有的情況,從中選取最小的時間和最大的時間。在這個問題中,我們可以定義螞蟻對象,Python代碼如下:

什麼是聰明!從“螞蟻爬杆”問題,一切明瞭

這裡,將杆看作一個座標軸,pos表示螞蟻在杆上的位置,也就是座標,direction表示螞蟻運動的方向,用+1和-1表示向左或向右,而state表示是否爬出杆,為0表示尚在杆上,而為1表示已經爬出杆了。

有了上述定義,就可以模擬螞蟻的運動來求解最長和最短時間了:

什麼是聰明!從“螞蟻爬杆”問題,一切明瞭

什麼是聰明!從“螞蟻爬杆”問題,一切明瞭

這裡,比較巧妙的應用了while...else...語句,想了解詳情的可以戳《Python中 else 塊那點事》。

那麼,此種算法的複雜度是多少呢?由於每隻螞蟻最初有2種朝向,所以算法的複雜度與螞蟻的數目有關,n只螞蟻的算法複雜度為O(2^n)。大家都清楚,指數函數的複雜度會隨著n急劇增大的,這也是在算法設計時需要避免的。

那麼,如何考慮更低複雜度的算法呢?

可以先考慮最短時間,這個問題比較簡單,可以將杆一分為二,左邊的螞蟻向左邊爬,右邊的螞蟻向右邊爬,這樣不會發生兩隻螞蟻相撞的情況。這種計算也會簡單。

什麼是聰明!從“螞蟻爬杆”問題,一切明瞭

如果考慮最長時間的情況呢?我們可以看看螞蟻相撞的情況:

什麼是聰明!從“螞蟻爬杆”問題,一切明瞭

這相當於兩隻螞蟻相遇後,繼續前進而非掉頭反向前進,這樣問題就會簡化了很多。這樣,求最大時間可以簡化為,判斷哪隻螞蟻離杆的兩個盡頭中較遠的一個最遠。Python代碼如下:

什麼是聰明!從“螞蟻爬杆”問題,一切明瞭

Swift - 螞蟻相遇次數問題

問題:在一條路的兩端, 從A點向B點一隻一隻地派遣10只螞蟻,B點向A點一隻一隻地派遣25只螞蟻。每當兩隻螞蟻面對面相遇,它們各自改變前進的方向,向與原來相反的方向前進。第一次相遇發生在所有螞蟻都上路以後。問最後有多少隻螞蟻到達A ,有多少隻螞蟻到達B ?一共有多少次螞蟻與螞蟻的相遇?

答案:最後有25只螞蟻到達A ,有10只螞蟻到達B ?一共有 10*25 = 250 次螞蟻與螞蟻的相遇.

這裡不說怎麼解出來的,而是根據問題的描述來進行模擬其行為,最後得到結果

覺得可以創建一個 Road 類,路有長度,可以用 length 屬性表示。

可是接下來,要怎樣才能讓螞蟻在路上面行走,並隨時記錄位置(以知道走到哪裡)?

看以下代碼:

什麼是聰明!從“螞蟻爬杆”問題,一切明瞭

在上面實現 locations 屬性的代碼中,使用了 Location 類型, 這就是下面將要創建的 Location(位置) 類。

位置依附路而存在,所以得有個 road: Road 屬性。

要將當前位置與其他位置區分開,可以加個 index: Int 屬性。

什麼是聰明!從“螞蟻爬杆”問題,一切明瞭

根據上面的 Location , 對 Road 中的 locations 的實現代碼進行相應的修改,修改後代碼如下:

什麼是聰明!從“螞蟻爬杆”問題,一切明瞭

現在有了路,就可以實現 Ant(螞蟻) 類了。

首先用 ID: Int 屬性,表示不同的螞蟻。

加個 location: Location 屬性,記錄螞蟻當前所在位置。

什麼是聰明!從“螞蟻爬杆”問題,一切明瞭

很簡單是吧!現在可以寫下面的代碼, 模擬一隻螞蟻在路上的“行走”了。

什麼是聰明!從“螞蟻爬杆”問題,一切明瞭

輸出如下:

什麼是聰明!從“螞蟻爬杆”問題,一切明瞭


分享到:


相關文章: