DP:
-
線性dp
-
P1091 [NOIP2004 提高組] 合唱隊形
比較簡單的一道題。求出以 \(i\) 結尾的最長上升子序列和以 \(i\) 為頭的最長下降子序列,相加 \(-1\) 即可。
-
P1052 [NOIP2005 提高組] 過河
如果不考慮 \(L\) 的範圍,那麼就是一道簡單的線性 dp 。
但是 \(L\) 很大,石頭數量很少,所以每相鄰兩個石頭的空隙一定很大。
前置知識:P3951 [NOIP2017 提高組] 小凱的疑惑給定兩個數 \(p\) 和 \(q\) ,他們最大不能湊出的數是 \((p-1)(q-1)-1\) 。所以中間空隙過多一定是可以被湊出來的,即可以壓縮中間的空隙,然後線性 dp 即可。
-
P1006 [NOIP2008 提高組] 傳紙條
求出 \(2\) 條從 \((1,1)\) 到 \((n,m)\) 的路徑。重複只算一次,求最大路徑和。
水題,不多贅述。記錄 \(dp_{A,B,C,D}\) 表示第一條走到 \((A,B)\) , 第二條走到 \((C,D)\) 。由於 \(A+B = C+D\) ,可以記錄他們的和,最佳化掉一維。
-
P1541 [NOIP2010 提高組] 烏龜棋
記錄 \(dp_{A,B,C,D}\) 表示用了 \(A\) 個 \(1\) 號卡片, \(B\) 個 \(2\) 號卡片, \(C\) 個 \(3\) 號卡片, \(D\) 個 \(4\) 號卡片。
暴力轉移即可 \(F_{A,B,C,D}=\max (F_{A-1,B,C,D},F_{A,B-1,C,D},F_{A,B,C-1,D},F_{A,B,C,D-1})+cost_{A+2B+3C+4D}\)
-
P2679 [NOIP2015 提高組] 子串
字首和最佳化線性 dp。(推式子題)
首先考慮如何 DP,然後再考慮如何最佳化。
狀態表示:\(f_{i, j, k}\)表示只用 \(S\) 的前 \(i\) 個字母,選取了 \(k\) 段,可以匹配 \(T\) 的前 \(j\) 個字母的方案數。
狀態計算:將 \(f_{i,j,k}\)表示的所有方案分成兩大類:
- 不用 \(S_i\),則方案數是 \(f_{i-1,j,k}\);
- 使用 \(S_i\),則方案數是 $ \sum f_{i-t,j-t,k-1}$,滿足 \(S_{i-t+1}=T_{i-t+1}\),\(t\) 從大到小列舉。
時間複雜度是 $ \mathcal{O} (nm2k)$。
我們發先 \(f_{i,j,k}\) 的第二項和 \(f_{i-1,j-1,k}\) 很像,可以考慮維護一個 \(tmp_{i,j,k}\)
- \(S_i=T_j\) , \(tmp_{i,j,k}=tmp_{i-1,j-1,k}+f_{i-1,j-1,k-1}\) 。
- \(S_i \neq T_j\),\(tmp_{i,j,k}=0\) 。
(把式子展開可以發現 \(tmp\) 的規律)。
然後空間會爆,寫滾動陣列或者 01揹包 倒序列舉最佳化掉第一維即可。
-
P5664 [CSP-S2019] Emiya 家今天的飯
求解所有方案數
\(f_{i,j}\) 表示前 \(i\) 種烹飪方式,做了 \(j\) 道菜的方案數。
-
狀態轉移:
第 \(i\) 種烹飪方式不做 \(f_{i,j}+= f_{i - 1,j}\) -
第 \(i\) 種烹飪方法做 \(1\) 道主要食材是 \(k\) 的菜:\(f_{i,j} += f_{i-1,j-1} * a_{i, k}\)
所有方案數量 $ A = \sum_{j = 1}^{n}f[n][j]$ 。
求解不合法方案:
\(dp_{i,j}\) 表示前 \(i\) 中烹飪方法,越界食材數 $ - $ 其他食材數 為 \(j\) 的方案數。
狀態轉移:
-
第 \(i\) 種烹飪方法不選:\(dp_{i,j} += dp_{i-1,j}\)
-
選越界食材 \(c\):\(dp_{i,j} += dp_{i-1,j-1} * a_{i, c}\)
-
選其他食材 \(dp_{i,j} += dp_{i-1,j+1} * (s_i - a_{i, c})\)
所有方案數量: $ B = \sum dp_{n,j} (j > 0)$ 。
\(A-B\) 即可。
時間複雜度 \(\mathcal{O}(n ^ 2m)\) 。
\(Tips\):
做差有可能為負數,把所有狀態加一個 \(+n\) 的偏移量即可。 -
-
總結:
對於線性 dp的問題,一般狀態定義為 \(f_{前\ i\ 個,滿足 \ ....\ 狀態}\),狀態可能很多,所以可能有很多維。
狀態轉移:考慮這個集合是由誰構成的,進行分類。比如分成 選 \(a\) 和不選 \(a\) ......
最佳化:如果狀態過多,考慮滾動陣列或者揹包最佳化,轉移中有求和,求最值等考慮用字首和,單調佇列最佳化。
-
-
區間dp
-
揹包
-
狀壓dp
-
樹形dp
-
倍增最佳化dp
貪心:
搜尋:
-
DFS
-
BFS
-
剪枝
數學:
-
數論:
-
組合數學
圖論:
-
拓撲排序
-
樹
-
LCA
-
最短路
-
二分圖
資料結構:
-
堆
-
並查集
-
線段樹
-
單調佇列
基礎演算法:
-
列舉
-
模擬
-
字串
-
排序
-
二分
-
位運算
-
構造
-
雜湊
-
找規律