Dp 學習筆記

\(\mathtt{dp}\) 總結

定義:

\(\mathtt{dp}\) 由 狀態,階段,決策三部分組成。ide

狀態:描述每一個子問題,而且答案能夠由這些問題組合出來。優化

階段:\(\mathtt{dp}\) 枚舉的 」 大方向 「 ,也就是最外層的循環,保證無後效性的前提,很重要的一部分。排序

決策:也就是狀態由哪幾個前綴狀態轉移得來。隊列

\(\mathtt{Ps:}\)遊戲

附加屬性:除階段之外的全部維度集合,輔助轉移,描述問題。it

最優屬性:也就是 \(\mathtt{dp}\) 裏存的值,也多是計數。class

使用 \(\mathtt{dp}\) 的基本條件:原理

  1. 重疊子問題
  2. 無後效性
  3. 最優子結構

重疊子問題: \(\mathtt{dp}\) 比通常的模擬快的前提,也就是重複的問題只算 1 次。搜索

無後效性:不能有狀態 互相轉移循環

最優子結構:當前狀態的最優解能夠由其前綴狀態轉移得來。


優化

狀態:

不遺漏,不重複 的覆蓋整個問題集合。

\(f(i,j)\) 的附加屬性通常是和其後續狀態 有關聯 的維度。

若是附加屬性 \(j\) 中的一部分能夠由剩下的 推導 出來,那麼這一部分能夠省略。

注意決策當中必要的狀態,不能省略。


階段:

最重要的維度,也就是首先枚舉這個維度,再在上面進行轉移,保證了階段無後效性,那麼就不用考慮其餘的維度有沒有後效性了。


決策:

轉移,考慮到全部的狀態,不能循環轉移。

線性 \(\mathtt{dp}\) : 狀態的各個維度成線性增加。

通常能夠設 \(f(i,j)\) 表示到了第 \(i\) 個階段,其附加屬性爲 \(j\) 的最優解,從階段 \(k\;(k<i)\) 轉移。

線性 \(\mathtt{dp}\) 通常運用在序列上面。其中的 \(j\) 是與其轉移到的狀態有關係的維度,也就是能夠影響後繼狀態的維度,通常是描述第 \(i\) 個階段最後一個的。

\(\mathtt{P4059}\)

按照末尾空格分類便可。


揹包:

揹包問題九講 崔添翼

\(\mathtt{Ps:}\)

找到容量,價值,重量,注意它們能夠互換。

\(\mathtt{Cf730J}\)

第 \(\mathtt{1}\) 問能夠用貪心,也能夠用揹包 (畫蛇添足) 。

第 \(\mathtt{2}\) 問能夠將水的容量和瓶子的數量做爲揹包的容量 ,瓶子裏原本最多裝有多少水,注意這時候是要以瓶子的數量爲第 \(\mathtt{1}\) 關鍵字更新。

這時候的揹包不一樣於其餘的,容量有 \(\mathtt{2}\) 個維度,由於只有肯定了 \(\mathtt{2}\) 個維度,才能最優化剩下的維度。

這一點要牢記。

\(\mathtt{Poj1742}\)

若是樸素轉移,須要 \(\mathtt{O(N\sum\limits{A_i})}\)

考慮把 可行性 問題轉化成 最優性 問題。

對於每種硬幣,若是求出現階段要湊成 \(i\) 面值的最小的張數,看是否大於 \(\mathtt{A_i}\) 就行了。

注意若是已經湊好了,那麼就不用轉移了。

此題的啓發:能夠將條件轉換成最優屬性


區間 \(\mathtt{dp}\) :

以區間長度做爲階段來轉移,通常從小區間轉移到大區間:

\(f(i,j)=f(i+1,j),f(i,j-1)\)

\(f(i,j)=f(i,k),f(k+1,j)\) 枚舉中轉點 \(k\) 。

其中能夠加入附加屬性。

\(\mathtt{P3147}\)

能夠轉換最優屬性,就是把狀態當中的維度與最優屬性互換。

\(\mathtt{P3205}\)

\(\mathtt{P4302}\)

有些區間 \(\mathtt{dp}\) 能夠用貪心優化:

\(\mathtt{P5851}\)

題解

其中的貪心策略爲:對於每頭牛,能夠假設它只吃 \(\mathtt{1}\) 個派。

如要保證最優:還需假設一個限制條件:每頭牛的 \(l_i\) 和 \(r_i\) 不超過區間 \((i,j)\) 。

\(\mathtt{Ps:}\) 首先處理出初始狀態,也就是沒法從其餘區間轉移的狀態,再從它們轉移到後繼狀態。


樹形 \(\mathtt{dp}\) :

一般設 \(f(i,j)\) 表示以 \(i\) 節點爲根的子樹內,附加屬性 \(j\) 的最優解。

若是碰到選取節點的問題,能夠設 \(f(i,j)\) 表示第 \(i\) 個節點選 / 不選的最優解。

\(\mathtt{[POI2001]Dynamite}\)

設 \(f(i)\) 表示走完 \(i\) 的子樹所需的時間以及村民裝遊戲時間較大值的最小值,\(g(i)\) 表示走完 \(i\) 的子樹而且走回 \(i\) 的時間。

若是直接轉移,順序會影響到結果,因此須要貪心。

相鄰交換法:

\(\max\{1+f(i),2+g(i)+1+f(i+1)\}>\max\{1+f(i+1),2+g(i+1)+1+f(i)\}\) 。

化簡,得:

\(g(i)-f(i)>g(i+1)-f(i+1)\) 。

按照這個排序便可。

\(\mathtt{[POI2014]FarmCraft}\)

樹上揹包

具備依賴性,好比要取 \(son(i)\) 就必需要取 \(\mathtt{i}\) 。

枚舉子樹的容量,以及分配給其兒子節點的數量。

設 \(f(i,j)\) 表示在 \(i\) 的子樹上,分配有 \(j\) 個節點,而且要選子結點,必需要選父親節點,\(v_i\) 表示其價值。

\(f(i,j)=f(i,j-k)+f(son(i),k)\)

其中的 \(j\) 要逆序枚舉,其中的原理和 \(\mathtt{01}\) 揹包是同樣的。

注意有時候 \(k<j\) 由於必需要選取父親節點。

\(\mathtt{P2014}\)

\(\mathtt{P1273}\)

\(\mathtt{Ps:}\)

這裏面的內容在揹包中的 泛化物品 中講到過。


狀壓 \(\mathtt{dp}\) :

若是轉移集合中的元素大小不超過 \(\mathtt{N}\) 且小於 \(\mathtt{K}\) ,那麼能夠將其壓縮成一個 \(\mathtt{N}\) 位 \(\mathtt{K}\) 進制數。

最多見的就是某個點選 / 不選,標記成 \(\mathtt{0/1}\) 。

\(\mathtt{P3052}\)

設 \(f(s)\) 表示選取集合 \(s\) 最小分組,\(g(s)\) 表示 \(s\) 保證最小分組以後末尾最小的容量。

枚舉最後一個加進來的數,看是否加入便可。

\(\mathtt{Ps:}\) 注意枚舉的順序,可能會漏掉某種狀況。

\(\mathtt{P1879}\)

對於矩陣類的 \(\mathtt{dp}\) 通常能夠考慮按照 行 / 列 枚舉。

以前提到過,附加屬性一定是能對後續狀態有限制做用的。

那麼只有上一行對這一行有限制做用,那麼狀態就顯而易見了。

\(\mathtt{P2915}\)


換根 \(\mathtt{dp}\) :

也叫 二次掃描法

求解對於每一個節點的最優解。

通常來講,第 \(\mathtt{1}\) 次計算某一個節點的貢獻,第 \(\mathtt{2}\) 次考慮子樹外 / 全局的貢獻,與父親節點的關係。

\(\mathtt{P3478}\)

\(\mathtt{Cf708C}\)


單調隊列

對於一個狀態轉移方程,能夠將與 前綴狀態 有關的信息提取出來,若是要求最小值 / 最大值,那麼能夠考慮單調隊列。

好比最大子區間,就能夠用單調隊列優化。

「一我的要是比你小,還比你強,那你就永遠打不過他了」——單調隊列

\(\mathtt{P2627}\)

\(\mathtt{P2569}\)


計數 \(\mathtt{dp}\) :

統計數量,保證 不重,不漏

\(\mathtt{Cf559C}\)

\(\mathtt{Poj1737}\)

\(\mathtt{P6596}\)

\(\mathtt{Ps:}\) 須要找 \(\mathtt{1}\) 個基準點,圍繞這個基準點進行轉移。

就好比某我的要麼是男生,要麼是女生,能夠以此來進行轉移。

\(\mathtt{Poj1037}\)

此題是個很經典的方法。

如要求排列的第 \(\mathtt{C}\) 個方案的題目,能夠用試填法。

\(\mathtt{P5367}\)

能夠預處理出 \(f(i,j,k)\) 表示 \(i\) 個木板,開頭爲第 \(j\) 小,是上升仍是降低的方案數。

那麼能夠從第 \(\mathtt{1}\) 塊木板開始枚舉,保證不超過 \(\mathtt{C}\) 便可。


數位 \(\mathtt{dp}\) :

通常有 \(\mathtt{2}\) 種模型:

求知足限制條件的第 \(\mathtt{K}\) 小的數,或者在區間 \((i,j)\) 內求出知足限制條件的數的總數。

\(\mathtt{Link:}\)

  • 數字組成的奧妙——數位dp
  • 數位DP合集 & 對數位DP的一點理解

\(\mathtt{Poj3208}\)

這道題是求第 \(\mathtt{K}\) 小的魔鬼數。

發現求排名的題,跟上面將的題很像。

能夠設 \(f(i,j),\;(j\le3)\) ,表示 \(i\) 位數,最長有 \(j\) 個連續的 \(\mathtt{6}\) 的魔鬼數。

\(\mathtt{Ps:}\) 這種題必定要注意是否有前導 \(\mathtt{0}\) 和是否限制在首位。

擬定一個轉移方程:

\(f(i,0)=9\times (f(i-1,0)+f(i-1,1)+f(i-1,2))\)

\(f(i,1)=f(i-1,0)\)

\(f(i,2)=f(i-1,1)\)

\(f(i,3)=f(i-1,2)+10\times f(i-1,3)\)

發現,對於第 \(\mathtt{1,2,3}\) 條轉移方程,是限制在首位的。

​ 對於第 \(\mathtt{4}\) 條轉移方程,是不限制在首位的。

也是用試填法,從高位往低位試填,由於高溫能夠限制數量。

記錄一個 \(\mathtt{p}\) 表示當前末尾有 \(\mathtt{p}\) 個連續的 \(\mathtt{6}\) ,用來轉移(注意若是 \(\mathtt{p=3}\),那麼後面的 \(\mathtt{p}\) 就不改變了)

當 \(\mathtt{p=3}\) ,能夠從 \(f(i-1,0/1/2/3)\) 轉移,發現覆蓋了所有的狀態 。

當 \(\mathtt{p<3}\) ,就須要注意最後 \(\mathtt{1}\) 爲是否有 \(\mathtt{6}\) ,能夠從 \(f(i-1,3-k-(j=6))\) 轉移。

\(\mathtt{P2602}\)

\(\mathtt{P2657}\)

\(\mathtt{P4317}\)

\(\mathtt{P3413}\)

\(\mathtt{P4172}\)

\(\mathtt{dp}\) 的特色就是重疊子問題,若是沒有重疊子問題,那麼就沒有優化了。

若是套模版,設 \(f(i,sum,num,lim)\) ,若是 \(num\%sum=0\) ,就返回 \(\mathtt{1}\) ,不然返回 \(\mathtt{0}\) 。

可是,這裏有個問題, \(num \le 10^{18}\) ,因此不能將 \(num\) 做爲狀態,也就不能轉移了。

因此,必須將其縮小,根據題目條件,存下 \(sum\) 就能夠了。

可是搜索的過程當中, \(sum\) 是會變化的,因此只能枚舉 \(sum\) ,看最後的 \(sum'=sum\) 且 \(nun\%sum=0\) 便可。

此題給咱們的啓發:若是狀態存不下,考慮將其(縮小)或將其做爲枚舉的部分,不能破壞 \(\mathtt{dp}\) 的特色。

資料來源:

【動態規劃】提升組的DP問候

【動態規劃】普及~省選的dp題

面向tg選手的DP練習題

xzy的樹形dp題單

一個動態更新的洛谷綜合題單

\(\mathtt{The\;End\;by\;GD.}\)

相關文章
相關標籤/搜索