Dynamic Programming

41  Download (0)

Full text

(1)

Dynamic Programming

Lecture by boook

Credit by howard41436

(2)

• 影片看了嗎

• Q&A

(3)

什麼是 dp?

什麼是 dp?

• 大家分享一下看完影片教學後,覺得什麼是 dp 吧!

(4)

什麼是 dp?

什麼是 dp?

• 簡單來說,就是把大問題分成小問題:

• 用小問題推出大問題的答案

• 所以建 dp 時我們要想兩件事:

• 1. 這個問題如何切成比較簡單的小問題?

• 2. 問題的答案如何從小問題的答案推得?

(5)

關於 dp 大家要知道的 關於 dp 大家要知道的

• 很多人覺得 dp 很難,但其實 dp 是簡單化問題的方法

• 看到 dp 題目時先建出可以轉移的狀態就好,先不管複雜度

• 找到不管時限會 AC 的 dp 算法,往往已經是成功的一半

• 接下來的各種優化方式會在未來的 dp 課程教到

• Dp 題目多練會進步得很快,因為從題目來建立狀態的方法在 很多題目中是相似的,多練就會變很強

• 想打好競賽, dp 一定要強!

(6)

哪些題目可能是 dp ? 哪些題目可能是 dp ?

• Dp 通常拿來解決兩種問題

• 1. 最優解問題

• 2. 計數問題

• 大家想想,這兩種問題是不是很適合從小答案算出大答案呢?

• 要有這兩個性質的 dp 才適合 dp

• 1. 重複子問題 ( 一格只會用一次的話開陣列存起來幹嘛? )

• 2. 最佳子結構

最優解問題中,要確定小問題的最佳答案跟大問題的有關

計數問題中,要確定轉移來源沒有多算少算

(7)

dp 複雜度分析 dp 複雜度分析

• dp 複雜度分成兩個部分:

• 狀態複雜度:

• 簡單來說 就是陣列開了多少格

• 每格都是一個狀態,都需要算出答案

• 轉移複雜度:

• 轉移複雜度則是 算出某一格的答案 需要的時間複雜度

• 可以觀察轉移式來得知

• dp 的總複雜度,就是總共有幾格 乘上 一格需要計算的時間!

(8)

dp 複雜度分析 dp 複雜度分析

• 因為 dp 總是分成這兩個部分,而壓複雜度有可能是從狀態下 手,也有可能是從轉移下手,因此這兩件事是要分開討論的

• 也就是”我的 dp 是 n^3” 這句話本身不夠表示你的 dp 演算法,

必須要說“我的 dp 是個狀態 n^2 ,轉移 n” 才夠精確

• 我們通常用 nD/mD 來表示一個狀態 O(N^n) ,轉移 O(N^m) 的 dp 演算法

• 在做每題 dp 時,都一定要好好寫出你的複雜度

(9)

DP bottom up 的種類 DP bottom up 的種類

• 以費氏數列舉例:

• 用「拉」的:

• for (int i = 2; i < n; ++ i)

• dp[i] = dp[i – 1] + dp[i – 2];

• 用「推」的:

• for (int i = 0; i < 100; ++ i) {

dp[i + 1] += dp[i];

dp[i + 2] += dp[i];

}

(10)

建構 dp 的小技巧 建構 dp 的小技巧

• 以下是對於常常想不到怎麼 dp 的同學的小技巧,不一定所有 人都覺得好用

• 狀態部分:先用題目中相關的變數開好開滿,記錄所有狀態

• 轉移部分:考慮最後一格 / 一次可能發生的狀況,獨立開來 後通常就變成前面算過的小問題了

• 如果發現轉移不了,就想想能不能把狀態開細一點,然後再回 去想怎麼轉移

• 再來就是一大堆的練習題!

(11)

跑步問題 跑步問題

• zj b589

• 有 n 段路,每段路有一個分數 ai ,你每段路可以用其中一種速

• 1. 用走的:你不會得到任何分數度

• 2. 用跑的:你會得到 ai 的分數

• 3. 用衝的:你會得到 2ai 的分數,但你下一段路得用走的

• 請問你最多能得到多少分?

(12)

跑步問題 跑步問題

• zj b589

• 有 n 段路,每段路有一個分數 ai ,你每段路可以用其中一種速

• 1. 用走的:你不會得到任何分數度

• 2. 用跑的:你會得到 ai 的分數

• 3. 用衝的:你會得到 2ai 的分數,但你下一段路得用走的

• 請問你最多能得到多少分?

(13)

跑步問題 跑步問題

• zj b589

• 有 n 段路,每段路有一個分數 ai ,你每段路可以用其中一種速

• 1. 用走的:你不會得到任何分數度

• 2. 用跑的:你會得到 ai 的分數

• 3. 用衝的:你會得到 2ai 的分數,但你下一段路得用走的

• dp[i][0] :沒限制

• dp[i][1] :下一段路得用走的

• 請問你最多能得到多少分?

(14)

跑步問題 跑步問題

• zj b589

• 有 n 段路,每段路有一個分數 ai ,你每段路可以用其中一種速

• 1. 用走的:你不會得到任何分數度

dp[i][0] = max(dp[i – 1][0], dp[i – 1][1])

• 2. 用跑的:你會得到 ai 的分數

dp[i][0] = dp[i – 1][0] + ai

• 3. 用衝的:你會得到 2ai 的分數,但你下一段路得用走的

dp[i][1] = dp[i – 1][0] + 2ai

• 請問你最多能得到多少分?

pastebin.com/raw/DTY0cwzh

(15)

區段和 區段和

• 給你一個陣列,並且有 q 次詢問,每次問某段區間 [L,R] 的數 字和

(16)

區段和 區段和

• 給你一個陣列,並且有 q 次詢問,每次問某段區間 [L,R] 的數

• 可以利用開另外一條陣列用 dp 的方式紀錄第 1 格至第 i 格的字和 數字和,這樣要求區段和時可以用 sum[R]-sum[L-1]

• 這個 sum 叫做前綴和陣列

• Sum[1] = a[1]

• Sum[2] = a[1] + a[2]

• Sum[3] = a[1] + a[2] + a[3]

• Sum[4] = a[1] + a[2] + a[3] + a[4]

• a[3] + a[4] = Sum[4] – Sum[2]

(17)

區段和 區段和

• 給你一個陣列,並且有 q 次詢問,每次問某段區間 [L,R] 的數

• 可以利用開另外一條陣列用 dp 的方式紀錄第 1 格至第 i 格的字和 數字和,這樣要求區段和時可以用 sum[R]-sum[L-1]

• 這個 sum 叫做前綴和陣列

• 這是非常非常常用的技巧,請大家一定要記得,看到跟區間和 有關的東西時常常可以這樣轉換

區間和 兩數的差

• 如果是二維的呢? ( 每次問你一個矩陣區塊的和 )

(18)

區段和 區段和

• 如果是二維的呢? ( 每次問你一個矩陣區塊的和 )

(19)

區段和 區段和

• 如果是二維的呢? ( 每次問你一個矩陣區塊的和 )

(20)

區段和 區段和

• 如果是二維的呢? ( 每次問你一個矩陣區塊的和 )

(21)

區段和 區段和

• 如果是二維的呢? ( 每次問你一個矩陣區塊的和 )

(22)

區段和 區段和

• 如果是二維的呢? ( 每次問你一個矩陣區塊的和 )

• A[l~L][r~R]

= S[L][R]

– S[L][r-1]

- S[l-1][R]

+ S[l-1][r-1]

(23)

最大連續和問題 最大連續和問題

• 影片中有最大完全不連續和問題,沒有其實更簡單的最大連續 和問題,此問題常常變形出現在別的題目

• n 個數字,選連續的一段數字,請問最大總和?

(24)

環狀最大完全不連續和問題 環狀最大完全不連續和問題

• acm 某 round pA

• 有 n 個數字圍成一環 a[0], a[1], …, a[n-1] :

你要選任意數量的數字,但任兩數不能相鄰,請問最大的數字 總和是多少?

(25)

環狀最大完全不連續和問題 環狀最大完全不連續和問題

• acm 某 round pA

• 有 n 個數字圍成一環 a[0], a[1], …, a[n-1] :

你要選任意數量的數字,但任兩數不能相鄰,請問最大的數字 總和是多少?

• a[0] 、 a[1] 不能同時選

(26)

環狀最大完全不連續和問題 環狀最大完全不連續和問題

• acm 某 round pA

• 有 n 個數字圍成一環 a[0], a[1], …, a[n-1] :

你要選任意數量的數字,但任兩數不能相鄰,請問最大的數字 總和是多少?

• a[0] 、 a[1] 不能同時選

把 a[0] 刪掉

把 a[1] 刪掉

(27)

最大不連續和問題 最大不連續和問題

• npsc 2017 決賽

• n 個數字,選一些數字,這些數字不能為連續的一段數字,請 問最大總和?

• 狀態如何設計才能轉移好所有的可能?

• 看似簡單,但請注意細節

(28)

計數 dp 計數 dp

• UVa 11420 - Chest of Drawers

• 有一個櫃子,上到下有 n 層,每層可以上鎖或不上鎖,請問讓 s 個櫃子是安全的有幾種方法

• 不安全的定義:這層未上鎖或上面那層未上鎖

(29)

計數 dp 計數 dp

• UVa 11420 - Chest of Drawers

• 有一個櫃子,上到下有 n 層,每層可以上鎖或不上鎖,請問讓 s 個櫃子是安全的有幾種方法

• 不安全的定義:這層未上鎖或上面那層未上鎖

• 用「推」的 DP : dp[n][safe][2]

• dp[i+1][j+1][1] += dp[i][j][1];

• dp[i+1][j][0] += dp[i][j][0] + dp[i][j][1];

• dp[i+1][j][1] += dp[i][j][0];

(30)

最大和矩陣問題 最大和矩陣問題

• 經典題

• 給你一個 n*m 的矩陣,所有的子矩陣中,最大的數字和是多

• 最裸最裸的做是 O(n^3m^3)=O(n^6)少?

• 合理的裸做是 O(n^2m^2)=O(n^4)

• 還能不能做到更好?

(31)

最大和矩陣問題 最大和矩陣問題

• 經典題

• 給你一個 n*m 的矩陣,所有的子矩陣中,最大的數字和是多

• 最裸最裸的做是 O(n^3m^3)=O(n^6)少?

• 合理的裸做是 O(n^2m^2)=O(n^4)

• 還能不能做到更好?

提示:能不能想辦法讓這題跟最大連續和扯上關係?

(32)

最大和矩陣問題 最大和矩陣問題

• 經典題

• 給你一個 n*m 的矩陣,所有的子矩陣中,最大的數字和是多

• 最裸最裸的做是 O(n^3m^3)=O(n^6)少?

• 合理的裸做是 O(n^2m^2)=O(n^4)

• 還能不能做到更好? Min(O(n^2 m), O(n m^2))

• 應該要怎麼做?

(33)

矩陣最大空方型問題 矩陣最大空方型問題

• 給你一個 01 矩陣,請問裡面最大的全部都是 0 的方形有多大?

(34)

矩陣最大空方型問題 矩陣最大空方型問題

• 給你一個 01 矩陣,請問裡面最大的全部都是 0 的方形有多大?

• dp[i][j] = ??? + 1

(35)

矩陣最大空方型問題 矩陣最大空方型問題

• 給你一個 01 矩陣,請問裡面最大的全部都是 0 的方形有多大?

• if (a[i][j] == 1) dp[i][j] = 0

• if (a[i][j] == 0)

dp[i][j] = min(dp[i – 1][j – 1]

, dp[i][j – 1]

, dp[i - 1][j]) + 1

(36)

矩陣乘法問題 矩陣乘法問題

• 給你一列矩陣,要從第一個乘到最後一個,保證兩相臨矩陣之 間都是可以做乘法的

• 一個 a*b 的矩陣乘上一個 b*c 的矩陣需要做 a*b*c 次數字的

• 矩陣有結合律,所以在不調換矩陣順序的狀況下可以用任意順乘法

• 請問把所有矩陣乘起來最少需要做幾次數字乘法?序做乘法

(37)

矩陣乘法問題 矩陣乘法問題

• 這種 dp 是前面沒遇到過的,前面遇到的題目都是按照前到後的 順序做,於是我們的狀態設計可以很容易的從前到後轉移

• 這種可以按照任意順序去操作的題目,怎麼設計狀態?

(38)

矩陣乘法問題 矩陣乘法問題

• 由於序列本身的順序不能改變,因此如果我們以某個區間當成 狀態,通常可以從左右的子區間轉移答案

• 例如本題, [L,R] 的矩陣要全部乘在一起,一定是先把 [L,K]

的矩陣乘在一起,以及 [K+1,R] 的矩陣乘在一起,再把剩下兩 個矩陣相乘

• 枚舉 K 後,剩下的部分是子問題

• 狀態: 2D

• 轉移: 1D

(39)

矩陣乘法問題 矩陣乘法問題

• zj d652 : 題目中沒出現矩陣,但其實就是矩陣乘法問題

• UVa 00348: 矩陣乘法,要印出最佳解的時候乘的順序

• Case 1: (A1 x (A2 x A3))

• dp 時記錄最佳的轉移來源,最後就能循序印出答案了!

• 類似經典題: Optimal Binary Search Tree

• 有興趣的人可以查查看這是什麼題目,然後想想看怎麼做

• 那我們接下來再來作一題區間的 dp

(40)

消消樂 消消樂

• UVa 10559

• 有一排方塊,每個方塊都有顏色

• 每次可以把連續顏色的一段消掉,得到 ( 消去長度 )^2 的分數

• 請問全部消完最多可以得到幾分?

• 跟剛剛那題很像的感覺,大家列列看狀態和轉移式吧!

(41)

消消樂 消消樂

• UVa 10559

• 有一排方塊,每個方塊都有顏色

• 每次可以把連續顏色的一段消掉,得到 ( 消去長度 )^2 的分數

• 請問全部消完最多可以得到幾分?

• 跟剛剛那題很像的感覺,大家列列看狀態和轉移式吧!

• 你確定你的演算法是對的嗎?

Figure

Updating...

References

Related subjects :