2009年12月15日 星期二

TopCoder Algorithm Tutorials - 從題目線索中找解法

摘錄自:How To Find a Solution

從題目給的線索中猜測該用什麼演算法解題。

直覺模擬
這類題目單純地會給很多步驟,條件(複雜度)不會太高,也不會太低,通常是在測試你的 coding 速度,因此不用想太多,照著做就對了。

BFS (廣度優先搜尋)
這類題目通常要求找出從起點狀態到終點狀態「最少步驟(最低成本)」的解,並且狀態間的轉移成本通常是1。常見題目都是給一個 N*M 的表格,有些格子不能通過,求要到達目的地的最短路徑。
因為 BFS 複雜度多半是線性的,因次 N (或 M) 很大(到百萬)也沒關係。

Flood Fill
BFS 找所有解,而非最小那個。

暴力搜尋、backtracking
暴力搜尋的條件(複雜度)不能太高,因為它就是(必須/可以)嘗試所有可能、然後找最好的。backtracking 也是暴力搜尋的一種,通常用遞迴做,並且題目給的條件(複雜度)會很低,那就很適合。

DP (動態規劃)
DP 的題目通常條件會是整數,而且不會太小或太大。題目可以被定義出「狀態」,透過「狀態轉移」,從較小(低)的狀態累積到較大(高)的狀態,最後找到答案。分析一個 DP 題目可以思考下列四點:
  1. 題目給的最大測試(複雜度)不會太大或太小
  2. 可以定義出一個「狀態」的樣子
  3. 大狀態的解是由小狀態累積/計算得來
  4. 有一個正確的方法可以從已知的狀態轉移(推算)到目前未知的這個。

最大流量 (Max Flow)
這類的題目通常在限制條件下會有 O(N^3) 或 O(N^4) 的解,且 N 不大 (500以內)。題目可以轉化成 graph 的形式來表示需求,並且 edge 上會有 capacitiy,最後求某個值要最大。

最大匹配 (Optimal Pair Matching)
題目在求兩個集合(set A, set B)中的元素,得以一對一配對成功的最大可能性。範例題目如下:
有 N 台車子要停進 M 個停車格中,但某些車子沒辦法前往某些停車格,且每台車子要開到某個停車格的距離不等,求順利停好所有車子、並使得需要開最遠才能停車的距離最短。
這是個最大匹配問題,因為:
  1. 每台車子(set A)對應一個車位(set B)
  2. 有些車無法到達某些車位 => set A 中的某些點無法與 set B 的某些點相連
把原問題轉換成 graph 的形式如下:
若某台車子與某個車位存在一條路可以通,則就有一條 edge 可以把他們連起來,edge 上的 cost 就是這台車到這個車位的最短距離。
這個 graph 建好之後,用 binary search 的方式找到最佳的解─某個值 C,能讓所有車都在不超過 C 的距離內找到一個沒用過的車位可以停車。具體作法是:設定一個 C 值後,把 graph 上大於 C 的 edge 通通拔掉,然後檢查是不是每台車都能找到一個車位。如果可以,就把 C 值減小,再來一次(所以原 graph 的數據要留著);如果不行,就把 C 值增大,也是再來一次。如此重複直到找到一個恰當的 C (正好可以成功、再小一點就不行的那個)。

線性規劃 (Linear Programming)(簡單版本)
題目通常給定一堆集合(sets),每個集合都有個標價(cost),且一個集合中的每個元素都有它的含量(quantity)。求用最少花費累積達到每個元素的指定份量。(不同集合間可能有相同元素,但含量不同)