DP 套 DP 與動態 DP

2022-10-09 11:21:10 字數 3796 閱讀 2112

即對於某種過程,我們需要 dp 進行,如果我們要對這個 dp 過程還要計數或者做其他的事,這時候我們需要對每一種 dp 的狀態都記錄下其對應的值,作為計數 dp 的狀態。

例題:cf578d

cf979e

cf1229e2

對於某種 dp 過程,我們可能需要修改這個 dp 中間的某些常數。

通常情況下這個 dp 過程可以寫成比較好的矩陣乘法的形式,由此 dp 就變成了矩陣乘法,然後動態維護矩陣乘法即可。

例題:p4719

cf1368h2

p3781

\(\\\)

\(\\\)

\(\\\)

考慮 lcs 是如何計算的,我們設 \(dp[i][j]\) 表示第乙個字串的前 \(i\) 個和第二個字串的前 \(j\) 個的 lcs 是 \(dp[i][j]\),轉移討論 \(s_i\) 和 \(t_j\) 的關係。

對於這個題,我們可以設 \(f[i][a_1][a_2][a_3]...[a_]\),表示我們填寫了 \(t\) 的前 \(i\) 位,且這個字串與 \(s\) 長度為 \(j\) 的字首的 lcs 為 \(a_j\)。

由於 \(lcs(s,t)=|s|-1\) 意味著有每個 \(t_i\) 如果要匹配,那麼只能和 \(s_\) 或 \(s_i\) 或 \(s_\) 匹配。

我們只需要記錄 \(f[i][a_][a_i][a_]\)。 同樣每個 \(a\) 可能的值不超過三種,於是狀態數就是 \(o(n)\) 的,轉移 \(o(1)\)。

另外,這個題還可以做 \(lcs(s,t)=|s|-k\) 的計數,其中 \(k\) 是乙個很小的量。

\(\\\)

\(\\\)

\(\\\)

\(\\\)

\(\\\)

考慮如何計算符合條件的路徑條數的奇偶性:設 \(dp[i]\) 表示以 \(i\) 結尾的符合條件的路徑條數的奇偶性,轉移列舉 \(i\) 的入邊即可。

現在考慮計數,由於邊是任意連的,所以我們第 \(i\) 個點的路徑條數奇偶分別的方案數僅與它與之前多少個結尾為黑/白,dp 為奇/偶的點連線。

於是我們設 \(f[i][a][b][c][d][0/1]\) 表示到第 \(i\) 個點,之前結尾為黑/白,dp 為奇/偶的點的個數分別為 \(a,b,c,d\),最後再記乙個總路徑條數的奇偶性。

由於 \(a+b+c+d=i-1\),轉移 \(o(1)\),因此 dp 是 \(n^4\) 的。

\(\\\)

\(\\\)

\(\\\)

考慮優化,首先前面所有的為 dp 值為偶數的,如果連邊也沒有影響,因此我們只需要記錄 \(b+d\)。

此外,當 \(a>0\) 與 \(c>0\) 時,我們發現目前這個點的方案數中,dp 值為奇數與偶數的方案數是相同的,因此我們只需要記錄 \(a\) 和 \(c\) 是否為 \(0\) 即可,然後 \(b+d\) 也因此不用記了。

於是複雜度可優化到 \(o(n)\)。

\(\\\)

\(\\\)

\(\\\)

\(\\\)

\(\\\)

考慮匹配如何計算,這裡的匹配無法用增廣路來記。因此我們記錄左邊前 \(i\) 個點與可以和右邊哪 \(i\) 個點之間有完美匹配。轉移列舉新增的點和右邊哪乙個匹配了,然後去重就行。

考慮計數,我們可以記錄所有右邊選擇 \(i\) 個點存在完美匹配的方案,將其記為狀態,即 \(f[i][s]\),計算在這種條件下的概率。轉移 \(2^n\) 列舉邊的情況以及新增的點和所有點連時能擴充套件出的情況。

我們爆搜發現 \(s\) 不超過 \(100000\) 種,可以通過。

\(\\\)

\(\\\)

\(\\\)

\(\\\)

\(\\\)

考慮重鏈剖分,如果我們 dp 出了所有輕鏈的答案,那麼我們如何對重鏈快速維護

設 \(g[i][0]\),\(g[i][1]\) 表示第 \(i\) 個點它所有輕兒子都不能選/任意選擇時,最大價值是多少;\(f[i][0]\),\(f[i][1]\) 表示 \(i\) 選/不選時的最大價值。

則可以列出方程:

\[f[i][0]=max(g[i][1]+f[son_i][0],g[i][1]+f[son_i][1])

\]\[f[i][1]=g[i][0]+f[son_i][0]

\]這時需要我們自己構造矩陣乘法的規則,我們可以將加法改為 max,乘法改為加法,可以證明這樣構造後依然滿足矩陣乘法的結合率。

於是我們可以構造出 \(i\) 的轉移矩陣:

\[\begin

g[i][1] & g[i][1] \\

g[i][0] & -\inf

\end

\]可以發現 dp 方程就變成了這樣:

\[\begin

f[i][0] \\

f[i][1]

\end

=\begin

g[i][1] & g[i][1] \\

g[i][0] & -\inf

\end

\begin

f[son_i][0] \\

f[son_i][1]

\end

\]於是我們使用線段樹維護矩陣乘法即可。

但是我們發現如果我們對線段的劃分如果不是按照從中點斷開,而是每次選乙個中點,使得左右每個點的輕子樹大小(以及自己)的和比較平均(均小於總和的一半),構成平衡樹的形式,那麼我們的複雜度可以達到嚴格的 \(o(nlogn)\)。

具體原因是我們每在樹上往父親跳一步,都會導致整體的子樹大小2,而跳輕鏈也會導致子樹大小2,於是複雜度就是 \(o(nlogn)\) 了。

如果還要寫線段樹,我們只需要每次分左右區間的時候讓左右的輕子樹和盡可能平均就行了。

\(\\\)

\(\\\)

\(\\\)

\(\\\)

\(\\\)

考慮 h1 的結論,我們每一行的點都會被染紅/染藍,或者每一列。

現在我們只考慮行,設 \(f[i][0/1]\) 表示對前 \(i\) 行,第 \(i\) 行染紅/藍的最小代價是多少。

那麼我們可以有轉移方程:

\[f[i][0]=min(f[i-1][0]+a_i,f[i-1][1]+b_i+m)

\]\[f[i][1]=min(f[i-1][0]+a_i+m,f[i-1][1]+b_i)

\]其中 \(a_i/b_i\) 分別為 \(i\) 這行染紅/藍後對邊緣點的貢獻。

我們可以列出和上一題差不多的轉移矩陣。

\(\\\)

\(\\\)

\(\\\)

\(\\\)

\(\\\)

設 \(f[i][j]\) 表示節點 \(i\) 的子樹中,選出乙個聯通塊的異或和是 \(j\) 的方案數且 \(i\) 必選。

設 \(g[i][j]\) 表示節點 \(i\) 的子樹中,選出乙個聯通塊的異或和是 \(j\) 的方案數。

設 \(f_i\),\(g_i\) 表示 \(f[i][j]\) 與 \(g[i][j]\) 的集合冪集數。

則我們可以列出轉移方程:

\[f_i=1+x^(prod_ f_j)

\]\[g_i=f_i+\sum_ g_j

\]乘法定義為異或卷積。

我們可以對 \(f\) 和 \(g\) 進行 fwt,這樣異或卷積就變成了點乘。

那麼轉移就可以變為

\[f_=1+p_\prod_ f_

\]\[g_=f_+\sum_ g_

\]這裡雖然矩陣不是很好設計,重鏈上的操作可以看作是重兒子乘上乙個常數再加上乙個常數。

於是我們的線段樹上可以記錄這裡面所有乘積,所有常數的貢獻之和以及所有 \(f\) 的和。複雜度依然是 \(log\)。

動態規劃 dp

威威貓系列故事 打地鼠 威威貓最近不務正業,每天沉迷於遊戲 打地鼠 每當朋友們勸他別太著迷遊戲,應該好好工作的時候,他總是說,我是威威貓,貓打老鼠就是我的工作!無話可說.我們知道,打地鼠是一款經典小遊戲,規則很簡單 每隔乙個時間段就會從地下冒出乙隻或多隻地鼠,玩遊戲的人要做的就是打地鼠。假設 1 每...

動態規劃,dp

線性動規區間動規樹形動規 區間動規 根據題目要求,全域性最優滿足區域性最優 典型題例 加分二叉樹 洛谷1040 題目介紹 題目描述 設乙個n 個節點的二叉樹t 的中序遍歷為 1,2,3,n 其中數字 1,2,3,n 為節點編號。每個節點都有乙個分數 均為正整數 記第j 個節點的分數為dj。二叉樹t ...

DP動態規劃

include include include include include include includeusing namespace std 動態規劃 利用子問題求解整個問題 關鍵 記錄子問題的解 列出狀態轉移方程 寫法 遞推 由邊界向上,最終得到目標問題的解 遞迴 由目標問題出發,向下遞迴...