1. 程式人生 > 實用技巧 >「賽前備戰」NOIp2020-提高 動態規劃訓練

「賽前備戰」NOIp2020-提高 動態規劃訓練

博主太菜,可能會炸聯賽,於是惡補一下 QAQ

動態更新

「eJOI2017」Experience

update - 2020.7.27

樹形 dp

\(f(x, 0), f(x, 1)\) 分別表示以 \(x\) 為根的子樹,\(x\) 所在鏈為向下(非嚴格)遞減、遞增時的答案。

題目中要求求極差,那麼結點 \(x\) 可能為最大值或最小值。

以向下遞減為例,我們在所以滿足 \(W_x \ge W_y\) 的所有子結點 \(y\) 中,將原本 \(y\) 的貢獻用 \(x\) 作為新的最大值替換,並更新 \(f(x, 0)\) 的答案。向下遞增也是同理,不過這裡是作為最小值,因此符號會改變。

在做結點 \(x\)

是,我們設 \(p = \sum\limits_{y \in \text{son}(x)} \max(f(y, 0), f(y, 1))\),並令 \(p\)\(f(x, 0), f(x, 1)\) 的初始值。

那麼狀態轉移方程(\(\leftarrow\) 表示最(大)值操作):

\[f(x, 0) \leftarrow \max\limits_{y\in \text{son}(x), W_x \ge W_y}\{p - \max(f(y, 0), f(y, 1)) + W_x - W_y\}\\ f(x, 1) \leftarrow \max\limits_{y\in \text{son}(x), W_x \le W_y}\{p - \max(f(y, 0), f(y, 1)) - W_x + W_y\} \]

時間複雜度 \(O(n)\)

「eJOI2018」山

update - 2020.7.27

\(f(n, k, 0), f(n, k, 1), f(n, k, 2)\) 表示 \([1, n]\) 中,建造了 \(k\) 座房子,且第 \(n-1\),第 \(n\) 個位置的狀態分別為 \((0,0),(1, 0), (0, 1)\) 時(\(0\) 表示沒有房子,\(1\) 表示有)的最小花費時間。

狀態轉移方程:

\[f(n, k, 0) = \min\{f(n-1, k, 0), f(n-1, k, 1)\} \\ f(n, k, 1) = f(n-1, k, 2) + \text{get}(a_n - a_{n - 1} + 1)\\ f(n, k, 2) = \min\{f(n-1, k-1, 0) + \text{get}(a_{n-1} - a_n + 1), f(n-1, k-1,1)+\text{get}(\min(a_{n-2}-1, a_{n-1})-a_{i}+1)\}\\ \text{其中 } \text{get}(x)=\max(x, 0) \]

時間複雜度 \(O(n^2)\)

「CSP2019-J」紀念品

update - 2020.7.27

揹包 dp

直接存物品的個數顯然原地昇天。但仔細想一下發現,轉換成統一在第 \(i\) 天買,然後在第 \(i+1\) 天賣,其實等價。因為即使對某種物品實際上並不操作,換成全賣了然後買回來也未嘗不可。

不難設計出一個比較暴力的狀態:\(f(i, j, k)\) 表示第 \(i\) 天,對於前 \(j\) 個物品,剩餘現金為 \(k\) 時,下一天手頭上的最大現金數。轉移方程顯然。

為了不空間爆炸,我們嘗試優化。第一維顯然可以縮掉——我們只要上一輪的最優值即可。剩下了兩維看著像一個揹包,於是倒序以下就只剩最後一維了。方程:

\[f(k) \leftarrow \max(f(k), f(k - P_{i, k})+P_{i, k+1}-P_{i, k}) \]

時間複雜度 \(O(TN\times \max P)\)