DP 2
LIS
Longest Increasing Subsequence
那什麼?
在給定一個序列中
會有很多遞增的子序列
找出當中長度最大的
如何定義 \(dp[i]\)
我們可以維護以第 \(i\) 項為終點的最大LIS大小
並定義為 \(dp[i]\)
接下來就是轉移式的部分!
兩種做法
- 資料結構
- 二分搜
先考慮二分搜
在原始序列 \(a\) 外,另外維護一個序列 \(b\)
令 \(b_i\) 為使 \(dp[j] = i\) 的最大 \(j\) 的 \(a_j\)
所以勒?
我們可以將陣列掃過一遍
然後對每個元素都放進 \(b\) 裡面
而 \(a_i\) 的位置會是
\(b.lower\_bound(a_i)\)
因此\(b\)最後的大小就會是LIS的大小
But
這個序列 \(b\) 不會是LIS的長相
可以想想怎麼還原LIS的樣子ㄛ
裸題
沒那麼裸,想想怎麼做XD
枚舉?DP?
最大二維子矩陣
給一個二維矩陣
求和最大的子矩陣
3 | 2 | -2 | 1 |
-1 | -4 | -1 | 1 |
1 | -1 | 2 | 2 |
0 | -1 | 1 | 1 |
最大二維子矩陣在這
枚舉?
有幾個子矩陣?
Ans:\(O(n^4)\)
好像沒有很好?
還記得一維的怎麼做嗎?
定義\(dp[i]\)為以\(i\)為終點的最大連續和
則轉移式為\(dp[i] = max(0,dp[i-1]) + a_i\)
先來點複習
在二維平面上有\(n\)個點,每個點有權重\(w_i\)
你可以以原點\((0,0)\)為圓心
任意選定兩個半徑形成兩個圓
並得到兩個圓間的環所覆蓋的點權重和
求最大權重和
\(n \leq 10^5,|x_i|,|y_i| \leq 10^9, |w_i| \leq 10^4\)
Text
要怎麼把一維的做法套上來?
對一個維度枚舉區間
另一個維度正常做最大連續和!
也就是一個維度\(O(n^2)\)
另一個維度\(O(n)\)
乘起來就是\(O(n^3)\)
題單
最大二維子矩陣
稍微難一點的變化題
小提示,如何運用資料結構來輔助DP
長得很像但不太一樣的題目
注意這題要想辦法壓到 \(O(n^2)\) ㄛ
背包問題
什麼是背包
給你 \(n\) 個東西,和一個可以乘載量為 \(m\) 的袋子
每個東西有重量 \(w_i\) 和價值 \(v_i\)
問你最大的價值為何
想greedy他?
(用CP值排序)
想想這個狀況
\(n = 3, m = 6\)
\(w_1 = 4, v_1 = 5\)
\(w_2 = 3, v_2 = 3\)
\(w_3 = 3, v_3 = 3\)
最佳解是取 \(p_2,p_3\)
但用CP值會只取到 \(p_1\)
考慮DP
令 \(dp[i][j]\) 為
考慮前 \(i\) 個物品
容量為 \(j\) 的背包能裝多少東西
轉移?
此時每個物品有被選與不被選兩種情形
所以我們的轉移式必須涵蓋這兩種狀態
轉移?
滾一下
此時你又可以發現,轉移式在轉移到\(dp[i][j]\)時
只會用到\(dp[i-1]\)的資料
因此你可以只要維護當前的\(dp[i]和dp[i-1]\)就好
同時取\(dp[i][j]\)時
你也只需要取 \(dp[i-1][k] s.t. k \leq j\)的資料
因此如果你讓for迴圈從 \(j=k\) 開始遞減
你可以只需要維護\(dp[j]\)就好
複雜度
你會發現有\(n \times m\)個轉移點
而轉移花費為\(1\)
因此總複雜度為\(O(nm)\)
奇怪的背包
剛剛上面講得基本上是指01背包問題
但其實還有很多種背包
etc:
有限背包, 無限背包
不過作法其實都是一樣的概念
但在細節上有差異,可以自己想想怎麼做
(還有可分割背包, 大數背包這種跟DP比較沒關係的類似題)
例題
背包是非常常見的經典問題
也有非常多的變化 etc. 很多計數問題
所以熟悉背包的概念非常重要ㄛ
裸題
實作一下剛剛講的東西就好ㄌ
好像哪裡不太一樣了?
懶得打ㄌ(X
現在變成有好幾個group
每個group中只能選一個
除了預算
還多了總量限制ㄛ
給你\(n\)個正整數
問你能不能讓某些數變成負的
使所有數加起來是\(0\)
\(n \leq 100, a_i \leq 1000\)
難難ㄉDP
提示一下,可以用帕斯卡三角形取\(C\)
LCS
Longest Common Subsequence
不免俗ㄉ看一下範例
\(|lcs(abcd,bc)| = 2\)
\(|lcs(ace,cae)| = 2\)
\(|lcs(abc,def)| = 0\)
DP狀態
定義 \(dp[i][j]\) 為
字串 \(A\) 的前 \(i\) 項和字串 \(B\) 的前 \(j\) 項的lcs長度
如何轉移?
考慮兩種情況,\(A_i = B_j 和 A_i \neq B_j\)
我們可以得到兩種轉移式
例題
裸題
給兩個長度小於1000的字串
求LCS長度
- Edit Distance
給你兩個字串\(A,B\)
定義一函式 \(f(s,t) = |lcs(s,t)|\times4 - |s| -|t|\)
你可以將 \(A,B\) 分別切為連續子字串 \(A',B'\)
求 \(f(A',B')\) 的最大值
矩陣快速冪
快速冪
把 \(k\) 次方拆成 2進位
\(O(\lg k)\) 時間計算 \(k\) 次方
矩陣
這樣就是一個矩陣
\(A\) 是一個 \(2 \times 3\) 的矩陣
如果要表達 \(A\) 的第 \(i\) 行第 \(j\) 列的項,那就是 \(A_{i, j}\)
矩陣加法
兩個行數列數都相同的矩陣可以做加法
矩陣乘法
zerojudge上有題目!
矩陣乘法
我們若有個 \(n \times m\) 的矩陣 \(A\),和\( m \times p \)的矩陣 \(B\)
則 \(A \times B\) 為 \(n \times p\) 的矩陣
其中,矩陣\( A,B \)可相乘若且唯若 \(A_{col} = B_{row}\)
(以上面為例就是那個 \(m\) 是一樣的)
詳細一點
我們直接示範看看
總之設 \(A,B\) 可相乘,令 \(A \times B = C\)
則 \(C_{ij} = \sum\limits^{A_{col}}_{k=1}A_{ik} \times B_{kj}\)
Why relevant?
- 線性代數會用到 (等一下會講的)
- 可以解決一些幾何問題 (高中的矩陣應用)
複雜度
矩陣乘法複雜度為 \(O(n^3)\)
其實不算太好
但矩陣快速冪題目的矩陣通常不會太大
所以這其實還好
矩陣乘法+快速冪
我們這邊先省略掉數學證明
總之矩陣乘法存在結合律
而且也可以對方陣取 \(n\) 次方
所以如果我們將DP式轉為一個矩陣
就可以用很快的時間運算了
題敘大致上是說:有6種西洋棋子可以用
每種棋子都有無限多個
你要取 \(n\) 個棋子排成一列
而國王跟皇后都必須取偶數個
求排列方法數模\(10^8+7\)
\(n \leq 10^9\)
先想想看 O(n) 作法
分三種狀態
- 國王跟皇后都有偶數個
- 國王跟皇后一奇一偶
- 國王跟皇后都有奇數個
轉移式呢?
\(dp[n][1] = 4 \times dp[n-1][1] + dp[n-1][2]\)
\(dp[n][2] = 2 \times dp[n-1][1] + 4 \times dp[n-1][2] + 2 \times dp[n-1][3]\)
\(dp[n][3] = dp[n-1][2] + 4 \times dp[n-1][3]\)
數學表達
令\(dp[n-1][1] = a,dp[n-1][2] = b,dp[n-1][3] = c\),則
數學表達
我們可以發現,每次往下一項走,都是再乘一次矩陣
所以我們可以把他轉成矩陣的 \(n\) 次方
矩陣快速冪丟下去
總而言之
矩陣快速冪可以使用的條件就是
我們的DP轉移式是取固定的狀態
而且都是把那些狀態的值乘上一個常數然後加起來
就能用矩陣快速冪做
恭喜你ACㄌ
例題
給定 \(f_1, f_2, a, b\)
令 \(f_n = bf_{n-1} + af_{n-2}\)
求 \(f_n (n \leq 10^9)\)
有四種顏色(紅藍綠黃)的油漆
而你有 \(n\) 個方塊要上色,且每個方塊只能上一種顏色
其中紅色跟黃色一定要有偶數個
請問有幾種上色方式?
覺得有點熟悉ㄅ
沒錯跟北市賽那題幾乎是一樣ㄉ
給一張圖,\(V \leq 100,E \leq 50000\),可能有重邊
給定一個起點和終點
求恰好經過 \(k\) 條邊的路徑有多少條
(路徑不需要簡單,也就是你一條邊走多少次都沒關係)
\(k \leq 10^{15}\)
區間DP
區間 DP 的架構
- 解決一個序列上的問題
- 把問題拆成對每個子區間分別解決
- done
Slime
- 有 \(N\) 隻史萊姆排成一列
- 第 \(i\) 隻史萊姆重 \(w_i\)
- 每次可以合併兩隻相鄰的史萊姆
- \(cost\) 是合併完的重量
- 全部合併在一起的最小花費
DP 2
By yungyao
DP 2
DDDDDDDPPPPPPP
- 390