• 沒有找到結果。

DP2 と特殊解題技巧

N/A
N/A
Protected

Academic year: 2023

Share "DP2 と特殊解題技巧"

Copied!
8
0
0

加載中.... (立即查看全文)

全文

(1)

DP2 と特殊解題技巧

samsam2310

2015 年 11 月 18 日(水曜日)

1 DP 優化

在前面的章節我們提到了用動態規劃(Dynamic Programming)來解決各式各樣的問題,而 在這裡我們要討論一些神奇的優化方式。

1.1 滾動

這算是特別提一下,通常在DP 得時候,記憶體都會很大,有時會超過我們的允許範圍

(比如10的8次方有時時間可以接受,但是空間不可以),這時我們可以觀察一下我們的 轉移式,然後利用某個維度只會利用到前幾層的性質,讓兩排記憶體交錯使用,減少記憶 體的空間。(可以透過複製一遍或是交換指標或是用變數取值)

1.2 單調隊列優化

先回憶一下雙向佇列(Deque)這個資料結構,他可以支援兩種操作:

•從兩端push新的元素進去。

•從兩端pop元素出去。

可以知道Deque完全涵蓋了Stack和Queue的操作。

而Deque通常用來優化DP中取極值的動作,尤其是要查詢多個範圍的極值,且這些範圍

滿足一定的單調性,我們將在下面一一討論。

1.2.1 Ansi =minLijRivj;LiLi+ 1, RiRi+ 1

簡單來說我們要依序查詢序列的某些區間的最大值,而且這些序列的區間左界和右界都是 遞增的。假設序列的長度為 N,如果我們對於每個區間都直接掃過一遍,時間複雜度會到 O(N2)。但仔細觀察可以發現,如果存在兩個元素vk, vh使得vk ≥ vh且k < h ≤ Ri,那麼 對於第 i筆之後的詢問,vk 絕不可能是區間的最小值。因此我們可以維護Deque 從前面

I

(2)

到後面是遞增的,即加入元素時保持單調性而從後面pop出元素,而當要查詢的時候先從 前端pop出過期的元素後,極值即為Deque中最前端的元素。

1.2.2 Ansi =minLijivj+ (didj);LiLi+ 1

對於這個情況,如果我們令ai = vi − di,原本的式子就可以改寫成 Ansi =minLijiaj +di

而因為對於同一個i來說di是固定的,這樣就轉化成第一種情況了。這個式子可以讓我們 加速背包問題的DP,回憶一下背包問題的 DP式,假設一個物品的重量為 w,價值為v 且有c個:

D(n, m) =max0≤kc;0≤mwkD(n−1, mwk) +vk 這個式子可以改寫為

D(n, wi+r) =max0≤jiD(n−1, wj+r) +v(ij)

可以看出D(n − 1, wj + r)即為vj,vi即為di。這可以讓我們在O(W N)的時間解決背包問 題,其中W是背包的耐重,N為物品的數量,是一個與同一個物品的數量c無關的算法。

1.2.3 Ansi =maxLijidjti+vj;LiLi+ 1, didi+ 1, titi+ 1

這個情況即是所謂的斜率優化,對於一個j,我們可以把每一個 dj ti + vj 看做是的一條直

線y = djx + vj,這些線的斜率都是遞增的,而在我們加入一條條的直線,維持凸包的單調

性,也就是說我們在加入新的一條線l時,假設Deque中最後兩條線為l1, l2,如果l1超 過l2的x 座標比l超過l2 的x座標大,那我們直接將l1 pop出,而每次查詢從前面pop 出過期或是已經被後面的線超過的元素。

1.3 四邊形優化

四邊形優化是一個非常恐怖的東西,當你對 DP的熱愛程度爆表了可以考慮研究一下。首 先我們先定義兩種DP問題。

1.3.1 1D/1D DP 這種式子的標準式

Di=minik<iDj +w(j, i)

簡單來說就是Di會它前面得出的答案 Dj再加上一個轉移的函數w(i, j)中的最小值。

II

(3)

1.3.2 1D/2D DP 標準式

Di, j =min0≤k<iDi, k+Dk+ 1, j+w(i, j);Di, i= 0

這種DP 式的意義大概是一個區間[i, j] 的答案會是將這個區間分成兩塊[i, k], [k + 1, j]的 分法中的最小值,再加上一個與k無關的權。

1.3.3 四邊形單調性

我們將單調性分成兩種。• 凹四邊形單調性如果對於任何a < b, c < d且 F(a, c) ≤ F(b, c),

就有F(a, d) ≤ F(b, d)。•凸四邊形單調性如果對於任何a < b, c < d且F(a, c) ≥ F(b, c),就

有F(a, d) ≥ F(b, d)。但直接驗證F滿足這個性質往往是不容易的,因此我們常用以下不等

式檢驗。•凹四邊形不等式如果對於任何a < b, c < d都有F(a, c) + F(b, d) ≥ F(a, d) + F(b, c),則F滿足凹四邊形單調性。• 凸四邊形不等式如果對於任何a < b, c < d都有F(a, c) +

F(b, d) ≤ F(a, d) + F(b, c),則F滿足凸四邊形單調性。更進一步的結果,我們只需要檢查

F(i, j) + F(i + 1, j + 1)和F(i + 1, j) + F(i, j + 1)的大小關係即可。

1.3.4 1D/1D凹性優化

回憶一下1D/1D的DP式:

Di=minik<iDj +w(i, j)

如果我們令F(j, i) = Dj + w(j, i),代表用j轉移i的花費,而Di就相當於F(i, k)中的最小值。

此時可以知道如果w(j, i) 滿足凹四邊形單調性,F(j, i) 也會滿足凹四邊形單調性。代表對 於i, i + 1, j, j + 1來說,一旦F(j, i) ≤ F(j + 1, i),也就是說如果用j來轉移i較j + 1來轉移i 好的話,那麼必有 F(j, i + 1) ≤ F(j + 1, i + 1),即接下來用j轉移 i + 1也會較用j + 1來的 好!換句話說如果我們用ki代表用哪一個j值來轉移i會得到最小的值,必有 ki ≥ ki+1。

利用這個單調性,我們便可以用特殊的方法加速。我們使用Stack維護當前最佳解,對於 stack裡的元素s 我們紀錄(L, R, p),代表對於所有 L ≤ i ≤ R,我們用 j = p來轉移到i最 佳。因此當我們要求 Di時只需先從Stack pop出過期的元素 (即R < i),之後把Stack的 top元素計算F(p, i)即可。而當我們要將 j = i加入Stack時,假設Stack的top元素為s,

有幾種情況:

1. F(i, s.L) ≥ F(s.p, s.L)

這代表用p轉移完勝i,因此我們保留s在Stack中。

2. F(i, s.R) ≤ F(s.p, s.R)

與上面相反,這代表用i轉移完勝p,因此我們直接將s給pop出。

3. F(i, s.L) ≤ F(s.p, s.L), F(i, s.R) ≥ F(s.p, s.R)

這時候代表存在一個界線,使得在界線前i較p好,而在後面 p較i好。由單調性我們可 以使用二分搜找出這個界線L′,並將s更新為(L′, R, p)。

最後我們再將i加入Stack中,即加入(i + 1, s.L − 1, i),便完成更新了。(當然有些時候我

III

(4)

們根本無需加入,如s.L − 1 < i + 1 時。複雜度為O(N lg N)。

1.3.5 1D/1D凸性優化

與凹性相反,我們用 ki代表用哪一個 j 值來轉移i 會得到最小的值,此時則為 ki ≤ ki+1。

這時候我們也用和剛才類似的方法優化,只不過我們將Stack改為Deque,取值的時候先 從前端pop出過期的元素,而加入新的值時,我們就從後邊刪除元素,最後一樣二分搜出 確切位置。

1.3.6 2D/1D凹性優化

2D/1D凹性優化並沒有特別特殊的性質,我們可以考慮枚舉i 後每次視為1D/1D的問題。

令Fi(j′) = Di,i+j′,此時有

F i(j′) =min0≤k<jF i(k) +ui(k, j′)

其中

ui(k, j′) = Di+k+ 1, j′−k−1 +w(i, i+j′)

只要證明ui(k, j′)有凹單調性,便可用前面所講的方法做到O(N2lgN)的複雜度。

1.3.7 2D/1D凸性優化

相較於2D/1D凹性優化,2D/1D凸性有更多的性質,因此有更好的優化方式。首先2D/1D

凸性在驗證上也比較容易,我們有以下的引理:2D/1D的DP式為 Di, j =min0≤j<iDi, k+Dk+ 1, j+w(i, j);Di, i= 0

如果w(i, j)為凸單調性的且w(i, i + 2) ≥ max(w(i, i + 1), w(i + 1, i + 2)),則Di,j也會符合凸 單調性。而且2D/1D凸性還有一個強大的性質:令K(i, j)為使Di,j達到最小值的k值,即 k為使Di,k + Dk+1,j + w(i, j)最小者,則有K(i, j − 1) ≤ K(i, j) ≤ K(i + 1, j)。也因為以上定理,

我們DP時可以從j − i = 1, 2,···的順序開始DP。當我們在求DPi,j時我們只需枚舉K(i, j −

1)到K(i + 1, j)即可,故對於所有 j − i = c的狀態,將他們都求出所需枚舉的狀態數只有:

0≤i<Nc

K(i+ 1, j)−K(i, j−1) =K(Nc, N)−K(0, c−1) +Nc=O(N) 故求出所有DP值只需要O(N2)。

1.4 插頭 DP

根據某篇文章,他又稱作「基於連通性狀態壓縮的動態規劃」。插頭DP通常用來處理 m

× n方格的一些組合計數,尤其是計算不同的某種特定路徑覆蓋的方法數。就拿最基本的

IV

(5)

來舉例,假設我們有一個m × n的方格,有些方格可以通行有些不能,求用數個漢米頓圈 覆蓋所有可以通行的方法樹有多少種?而插頭 DP的想法即是從右到左,從下到上依序討 論每一個方格內路徑的樣式,即路徑要從方格的上下左右哪個相鄰方格進來/出去。雖然說 我們要求漢米頓圈覆蓋覆蓋的方式,但我們可以想像成,我們先用路徑的方式討論,只要 最後能把路徑「接起來」即可。如圖所示,假設我們正在討論內部為交叉線條的那個方格,

而我們DP的狀態便紀錄那條粗線的每個線段,是否有「插頭」,即是否有路徑通過那個位 置,而當我們要遞推到下一格時,可以知道格子內路徑的樣式可以為那些只和格子右邊以 及下邊的插頭有關,因此我們只需枚舉一些情況就可以了,而如果格子是不能通行的,那 相當於右邊以及下邊都不能有插頭。因此數個漢米頓圈覆蓋我們只需用2進位即可儲存狀 態,但隨著題目越複雜,存的狀態可能也會越複雜,比如題目如果要求只用1個漢米頓圈 覆蓋,那就需要用3進制儲存。詳細的話有興趣可以研究看看。

2 特殊解題技巧

2.1 Meet in the middle

HOJ 132給你最多30個物品,每個物品有價值c(−109 ≤ c ≤109),問是否存在一個集合S 滿足iSci = 0。很簡單的想法是O(2n)爆搜,然後亂剪枝。但這實在不是很營養的辦法,

那所以有沒有複雜度合理一點的算法呢?

不難發現任何一個集合都是從前15個物品中找一些、後15個找一些,然後合併出來。所 以我們可以把前 15個跟後 15個的所有子集合(215 + 215)算出來,然後對於前半的每種 子集合,搜尋看說後半的每種子集合中是否有集合跟他加起來是0的,這明顯把後半每個 子集合的權重都丟到平衡樹裡,就可以 O(lgn)的時間完成搜尋。這樣子的時間複雜度是 O(2n2×2 + 2n2×lg2n2),這最大也就500000左右而已,相當理性的計算量。

Exercises!!

1. Balanced Cow Subset (USACO open 2012 gold)給你 n(≤ 20)隻乳牛,每隻乳牛有他

的產乳量mi,你現在要把這些乳牛分成黑牛、棕牛和白牛,滿足黑牛的總產乳量=棕牛的

產乳量,問有幾種" 把牛分到白牛的方法"。

2.2 啟發式合併

HOJ 191給你一顆有根樹(100000個節點),某些葉子上有重量為wi的寶藏,對於每個非

葉節點輸出它的有寶藏的葉子小孩們重量差距最小是多少。

第一眼應該會想到一個解法,對於每個節點把她所有寶藏葉子小孩排序好,然後掃過去計

V

(6)

算答案。但這複雜度是很不妙的O(N2)。

那這時應該可以想到了一個優化,對於一個節點,你要計算的其實只是他各個寶藏葉子小 孩對其他顆子樹的最小差距,也就是找他在某顆子樹的lower bound或是upper bound跟 他的差距取min。不意外的話你現在有一個做法是這樣:

對於一個點依序把每顆子樹的所有寶藏小孩加進自己的集合,但加進去之前不忘更新這個 點的答案。

為了方便取upper bound跟lower bound 所以會用平衡樹當作自己的" 集合" 的資料結構,

所以複雜度會變成O(N2lgN),更不妙了。

那到底怎麼辦OAOOO。

走投無路的你開始胡思亂想了。如果我每次合併平衡樹的時候是由小顆的一個一個點加進 大顆的樹,那複雜度應該會好一點吧....

到底會好到多少呢? 你發現你的複雜度其實就是 "N×�����×�������",所以每個寶 藏小孩插入別人的次數是多少呢? 因為每次都是由小的插到大的,所以假如這次某隻寶藏 小孩所在平衡樹的大小是,那插入後所在的平衡數大小至少是2x,而且如果這隻寶藏小孩 所在的平衡數大小就是 N話,那他在也不會去插入任何人了(因為他已經在最大的平衡樹 裡了),所以他只會待過lgN顆平衡樹。所以總複雜度就變成了O(N lg2N),真是神奇。

Exercises!!

1. Tree rotations (POI XVIII)給你一顆二元樹,滿足每個非葉節點都有兩個小孩,每個葉

子都有一個1~n的數字且互不相同,讓S為所有葉子以前序表示法排列而成的序列,你 現在可以對這棵二元樹任一個非葉節點對調他的左子樹跟右子樹,問你最小要調換幾次才 能使新的S的逆序數對數最少。

2.3 莫隊算法

神奇大陸人發明的演算法。

通常我們再寫RMQ問題的時候,都要寫複雜的資料結構,對於時間不多的資訊競賽來說,

可能是造成你失敗的大坑,因為你可能身陷其中而無法自拔,導至最後甚麼都沒寫出來。

莫隊算法提供了一個不一樣的作法。基本上他只能用來解靜態的區間查詢問題。比如問你 這個區間的最大值,或是區間的眾數。我們可以分成兩個部份,第1是把問題轉換成你有 一個區間,你可以從左右兩邊擴大或縮小區間。接著我們把所有查詢離線,在依照某個順 序處理。

那個順序就是,把序列切成

N 塊,把左界在同一塊的查詢分成一組,然後每組再依照 右界排序。這樣的話,我們依照順序作查詢時,我們的同一塊裡面,左界會在

N 的區 間內抖動,右界會遞增,複雜度變成O(

N (Q+N)),Q 是詢問次數。因為我們的左 界有兩種狀況,分別是抖動和移到下一格,假設我們 K個分成一塊好了,那抖動複雜度

VI

(7)

O(Q∗K),而移動到下一格的複雜度,因為有N/K塊,,一次最多移動2*K,所以就是 O(N/K 2∗K) = O(N)。而右界在每一塊裡面都是遞增,複雜度是 O(N/K ∗N),最後 複雜度就是O(Q∗K+N +N/K∗N),我們發現取K =

N 好像是個不錯的辦法。莫隊 的重點是要可以離線、不會有修改、可以擴大或縮小區間,上面的複雜度是基於擴展和縮 小複雜度是O(1),如果你用了甚麼set還是map的話就還會再往上跳。

Exercises!!

TIOJ 1699 Problem I害蟲決戰時刻

給你一堆蟲的編號,多筆詢問,問你一個區間內有沒有任何一種蟲出現的次數多於「區間 長/K」。

2.4 拉斯維加斯和蒙地卡羅演算法

這兩種演算法是很有名的賭博演算法,被廣泛應用在喇分跟現代物理學的運算上。

當我們在做一些演算法時,我們其實有機率一次就作對,但是也有機率會錯。拉斯維 加斯是一種賭博演算法,他賭的不是答案的正確性,而是使用的資原。你的問題通常會 表現成"YES"和"NO",但是其中一種是有機率錯的,比如 YES 的正確率只有 1/2 之類 的。這種情況下,你可以在NO發生時就停止演算法,進而減少使用的資源,比如快速排序法。

然而有時候,我們沒有辦法算完全部的狀況,這時後就可以用萌地卡羅演算法,這個演 算法主要是說,我們用隨機抽樣來統計結果,結果會愈來愈接近我們的答案。搭配上第1 種演算法,我們可以得出,因為NO絕對是錯的,而YES真的是YES的機率P,那連續

YES兩次就是P*P,N次就是PN,所以我們可以多做幾次,直到錯誤率達到我們想要的

標準,或是資源用盡。

Exercises!!

STEP5 0129驗算

給你很多個矩陣乘法的題目和結果,請你驗算這些矩陣乘法有沒有算錯。

2.5 摹擬退火演算法

有點算是萌地卡羅的一種應用,通常用在物理學和計算幾何上。

金屬晶體在降溫得過程中會不斷隨機跳動,慢慢得退進能量最低的晶格中,最後產生能量 最低的結果。而摹擬退火就是摹擬這個過程。如果我們有很多點在平面上,我們希望找出 一個點,到所有點的距離和最小,我們一開始一定是想到爆搜拉、三分搜之類的,但是那 些都太麻煩了。我們可以利用摹擬退火,先選一個點,寫一個估價函數(這裡就是計算到

VII

(8)

所有點的距離和),設定一個長度(也就是現在的能量,之後會慢慢減少)。之後開始隨機 亂跳,如果跳過去發現估價函數的值變大了,那就回來,不然就跳過去,同時能量會慢慢 衰退(可以將距離乘以0.9 之類的方式)。這樣最後我們就可以找到一個不錯的解,至於 結果取決於能量衰退的速度和精度,如果衰退太快,可能會來不及跳到最佳解,太慢又會 太浪費資源,我們只要讓能量衰退到一定的標準(通常跟題目要求的精度有關係),就可 以結束掉演算法。

VIII

參考文獻

相關文件

第1~7題包含單選題與非選題。單選題每題7分。非選題依各題配分。 (一)1 ~ 3 題為題組 閱讀下文,回答1-3題。 我叫「喬」,這是同事米爾頓.大衛森對我的稱呼。他是程式設計師,而我是電腦程式。我是萬 用自動機複合體的一部分,與遍布世界的其他部分連成一體。我什麼都知道,幾乎什麼都知道。

本的 ppt 檔與學生分享與討論生命形成之獨特性,以及成長過程 中可能面臨的困擾與危險。在與學生互動討論中,教師分享懷孕 養兒育女的經驗,讓學生了解生命的成長需要許多人的協助。同 時藉由對自己姓名的探索及與家人互動中了解生命傳承的重要 性,並在其中學會珍愛自己。 我們的名字都有一個故事,他可 能很特別,也可能很平常。除了這個命名的故事之外,你也可