-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Knuth_optimization.md #76
base: main
Are you sure you want to change the base?
Conversation
draft
Hi @harry900831, the outline and most of the content is finished, except problem descriptions and solutions for the exercises. I will add them as soon as possible. I think I can ask for comments first so I can fix the content. Thanks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- 現在看下來這三個主題塞在同一篇內容會有點太多,同時對你完成這次作業來說也會有點太多,我覺得可以分成三篇1. 1D/1D單調 2. Knuth optimization 3. divide and conquer optimization。看你想要先 focus 在哪一篇我們先 merge 那一篇進去。
- 目前的大問題是 1. 解釋的不是很清楚,至少我看過去還是看不懂QQ 2. 要準備 teamplate code 3. 對於應用的題目需要證明他確實有這個單調性
- 每一個技巧希望都能詳細講解個兩題,題目最好使用 CF, Atcoder, CSES 等等真找不到的話再去用一些不常用的OJ
- 我的建議是多用圖片輔助解釋,但是圖片上也需要標示清楚,先專心將其中一個技巧講清楚就好,那就已經會花掉很多時間了。不要只針對我有 comment 的地方去修改。
@@ -0,0 +1,552 @@ | |||
# Monotone optimization |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
這個主題名稱是你自己訂的嗎?
還是真的有這個名詞?
- **凹四邊形不等式** (concave Monge condition):若 \\(A\\) 滿足凹四邊形不等式,則 \\(a+d\ge c+b\\) | ||
- **凸四邊形不等式** (convex Monge condition):若 \\(A\\) 滿足凹四邊形不等式,則 \\(a+d\le c+b\\) | ||
|
||
<img src="image\Monotone_optimization\blank.JPG" width="500" style="display:block; margin: 0 auto;"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
請避免非白底與手繪風的圖示
- **凹四邊形不等式** (concave Monge condition):若 \\(A\\) 滿足凹四邊形不等式,則 \\(a+d\ge c+b\\) | ||
- **凸四邊形不等式** (convex Monge condition):若 \\(A\\) 滿足凹四邊形不等式,則 \\(a+d\le c+b\\) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
只有 Monge 有大寫正常嗎?
- **凹完全單調** (concave totally monotone):若 \\(A\\) 滿足凹完全單調,則 \\(a\le b\implies c\le d\\) | ||
- **凸完全單調** (convex totally monotone):若 \\(A\\) 滿足凸完全單調,則 \\(a\ge b\implies c\ge d\\) | ||
- **凹四邊形不等式** (concave Monge condition):若 \\(A\\) 滿足凹四邊形不等式,則 \\(a+d\ge c+b\\) | ||
- **凸四邊形不等式** (convex Monge condition):若 \\(A\\) 滿足凹四邊形不等式,則 \\(a+d\le c+b\\) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
凹 -> 凸
|
||
首先來看看單調性在 1D/1D 的應用。定義一個 1D/1D 的 DP 問題: | ||
|
||
> 要求的是一維代價 \\(dp[j]\\): \\[dp[j] = \underset {0\le i\lt j}{min}\\{f(i,j,dp[i])\\}, \forall 1\le j\le n\\] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
請使用函數表示的方式 f(i) 而非 dp[i]
習慣的表示方式 是要求 i 然後去枚舉 j
所以應該是 f(i) = f(j) + .... for all j < I 之類的
> **Monge condition implies Monotonic Optimal Split Point** | ||
> | ||
> 當上述 2D/1D 問題的代價 \\(w\\) 符合凸四邊形不等式,即: | ||
> \\[dp[i]\[j]+dp\[i+1][j+1] \ge dp\[i][j+1]+dp\[i+1][j]\\] | ||
> 則決策點具有單調性 : \\(opt\[i][j-1]\le opt\[i][j]\le opt\[i+1][j]\\),即 \\(dp\[i][j]\\) 的決策點位在 \\(dp\[i][j-1]\\) 到 \\(dp\[i+1][j]\\) 的決策點之間。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
請使用 f(i, j) and opt(i, j)
|
||
<details><summary> Solution Code </summary> | ||
|
||
- 觀察可發現代價函數 \\(C\\) 滿足 Monge condition (等號都成立),可以套用 Knuth Optimization 解決。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
需要證明
> | ||
> 令 \\(F(i,j)\\) 為一個對所有 \\(1\le i\le j\le N\\) 的正整數 \\(i,j\\) 都有定義的函數。對於所有的 \\(1\le j\le N\\),求 \\(\underset {i\le j}{min}\space F(i,j)\\) 或 \\(\underset {i\le j}{max}\space F(i,j)\\)。 | ||
|
||
直接來看一題題目最清楚。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
為什麼這個技巧又直接看題目比較清楚了
前面都沒有這個待遇XD
|
||
不妨先假設 \\(B\\) 具有凹單調性且 \\(B\\) 中所有元素皆相異 (若有相同元素隨意定序即可),若我們已經知道 \\(x = B\[i]\[j]\\) 是第 \\(j\\) 行的最小值,也就是 \\(dp\[j]\\) 的答案,則根據凹單調性可知: | ||
|
||
- 對於任意 \\(i^{\prime}\lt i,j^{\prime}\lt j\\) 有 \\(B\[i]\[j^{\prime}]\lt B\[i^{\prime}]\[j^{\prime}]\\) (\\(\because B\[i]\[j]\lt B\[i^{\prime}]\[j]\\),由凹單調的逆反命題得知),因此所有位於 \\(B\[i][j]\\) 左上角的元素都不可能是最佳的轉移來源。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
誰的最佳轉移來源
l = tp.l-1, r = tp.r; | ||
while(r-l > 1) | ||
{ | ||
mid = (l+r)>>1; | ||
if(cal(tp.pos,mid) >= cal(i,mid)) l = mid; | ||
else r = mid; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
這 l, r 應該可以換成更有效率的做法
dc436b1
to
d6814ab
Compare
|
||
要優化 DP 算法可以從以上 3 種下手,本文要介紹的 Knuth's Optimization 是透過減少**每個狀態轉移的狀態數**來加速 DP。Knuth's optimization 通常用於解決具有以下形式轉移的 2D/1D 問題: | ||
|
||
> 要求的是一個二維函數 \\(dp(i,j)\\):> \\[ dp(i,j) = w(i,j) + \underset{i\le k\lt j}{min} \\{dp(i,k)+dp(k+1,j)\\}, \forall 1\le i\lt j\le n\\] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:>
what is this symbol?
Knuth's Optimization 的應用可說是非常簡單,以 [Atcoder DP contest-Slime](https://atcoder.jp/contests/dp/tasks/dp_n) 為例,我們可以列出這個 DP 式(在此就不詳細解釋細節):\\[dp(i,j) = w(i,j) + \underset{i\le k\lt j}{min}\\{dp(i,k)+dp(k+1,j)\\}\\] | ||
|
||
可用下面這段 \\(O(n^3)\\) 的程式片段求出答案 \\(dp(1,n)\\) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it's worth to make this problem as an example
and explain what is w(i, j)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
這會讓讀者閱讀比較順暢
並不是所有人都知道slime是什麼
|
||
- Note : \\(x\\)D/\\(y\\)D 問題是指有 \\(N^x\\) 子問題,每個子問題需 \\(N^y\\) 子問題轉移,因此有時間複雜度為\\(O(N^{x+y})\\) 的 DP 做法。 | ||
|
||
Knuth's Optimization 的應用可說是非常簡單,以 [Atcoder DP contest-Slime](https://atcoder.jp/contests/dp/tasks/dp_n) 為例,我們可以列出這個 DP 式(在此就不詳細解釋細節):\\[dp(i,j) = w(i,j) + \underset{i\le k\lt j}{min}\\{dp(i,k)+dp(k+1,j)\\}\\] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
需要把 base case 也列上去
```cpp= | ||
for(int i=1;i<=n;i++) | ||
{ | ||
for(int k=1;k<=n;k++) | ||
{ | ||
dp[i][k] = (i == k ? 0 : INF); | ||
} | ||
} | ||
for(int len=2;len<=n;len++) | ||
{ | ||
for(int i=1;i+len-1<=n;i++) | ||
{ | ||
int j = i+len-1; | ||
for(int k=i;k<j;k++) | ||
{ | ||
dp[i][j] = min(dp[i][j], dp[i][k]+dp[k+1][j]+pre[j]-pre[i-1]); | ||
} | ||
} | ||
} | ||
``` | ||
|
||
若我們知道這題可套用 Knuth's Optimization 要運用…… | ||
|
||
只需將 **\\(i\le k\lt j\\)** 換成 \\(opt\[i][j-1]\le k\le opt\[i+1][j]\\) 就好! | ||
|
||
```cpp= | ||
int i,j,k,len; | ||
for(i=1;i<=n;i++) dp[i][i] = 0, opt[i][i] = i; | ||
for(len=2;len<=n;len++) | ||
{ | ||
for(i=1;i+len-1<=n;i++) | ||
{ | ||
j = i+len-1; | ||
dp[i][j] = INF; | ||
int optl = opt[i][j-1]; | ||
int optr = opt[i+1][j]; | ||
for(k=optl;k<=optr;k++) | ||
{ | ||
if(dp[i][j] > w(i,j) + dp[i][k] + dp[k+1][j]) | ||
{ | ||
dp[i][j] = w(i,j) + dp[i][k] + dp[k+1][j]; | ||
opt[i][j] = k; | ||
} | ||
} | ||
} | ||
} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why the style of two code is not the same?
I would prefer change the first one to something like:
vector<vector<int>> dp(n + 1, vector<int>(n + 1, INF));
auto w = [&](int i, int j) {
return pre[j] - pre[i - 1];
}
for (int i = 1; i <= n; i++) dp[i][i] = 0;
for (int len = 2; len <= n; len++) {
for (int i = 1; i + len - 1 <= n; i++) {
int j = i + len - 1;
for (int k = i; k < j; k++) {
int val = dp[i][k] + dp[k + 1][j] + w(i, j);
dp[i][j] = min(dp[i][j], val);
}
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please verify the code by yourself
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, if you are not demanded on using your own coding style, I would prefer the code to be formated by clang-format
\\(opt\[i][j-1]\\) 為 \\(dp\[i][j]\\) 的最佳轉移點,神奇的事發生了,這段程式的複雜度為 \\(O(n^2)\\)! | ||
|
||
接下來我們來詳細解釋 Knuth's Optimization 實際上做了什麼。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
我覺得解釋玩什麼是四邊形優化,再來把 slime 優化到 O(n^2) 會比較順
不知道你怎麼看
Lemma : 假設以上條件成立,\\( dp \\) 函數也會滿足凸四邊形不等式。 | ||
|
||
- 定義 \\( dp_t(i,j) = dp(i,t)+dp(t+1,j)+w(i,j) \\) | ||
- 對於 \\(i\lt j\\) 我們可以找到 \\(p ,q\\) 使 \\(i\le p\le q\lt j-1\\),且令 \\(opt(i,j-1) = q\\) | ||
|
||
如果我們能證明 \\(dp_p(i,j-1) \ge dp_q(i,j-1) \implies dp_p(i,j) \ge dp_q(i,j) , \forall i \le p \lt q\\) | ||
|
||
則顯然 \\( opt(i,j-1) \le opt(i,j) \\)。 | ||
|
||
對於 \\( p+1 \le q+1 \le j-1 \le j \\),根據四邊形不等式我們有:\begin{align} | ||
&dp(p+1, j-1) + dp(q+1, j) ≤ dp(q+1, j-1) + dp(p+1, j) \\\\ | ||
\implies& (dp(i, p) + dp(p+1, j-1) + C(i, j-1)) + (dp(i, q) + dp(q+1, j) + C(i, j)) \\\\ | ||
\leq& (dp(i, q) + dp(q+1, j-1) + C(i, j-1)) + (dp(i, p) + dp(p+1, j) + C(i, j)) \\\\ | ||
\implies& dp_{p}(i, j-1) + dp_{q}(i, j) ≤ dp_{p}(i, j) + dp_{q}(i, j-1) \\\\ | ||
\implies& dp_{p}(i, j-1) - dp_{q}(i, j-1) ≤ dp_{p}(i, j) - dp_{q}(i, j) \\\\ | ||
\end{align} | ||
又 | ||
\begin{align} | ||
&dp_{p}(i, j-1) \geq dp_{q}(i, j-1) \\\\ | ||
&\implies 0 \leq dp_{p}(i, j-1) - dp_{q}(i, j-1) \leq dp_{p}(i, j) - dp_{q}(i, j) \\\\ | ||
&\implies dp_{p}(i, j) \geq dp_{q}(i, j) | ||
\end{align} | ||
如此一來就證明 \\( opt(i,j-1) \le opt(i,j) \\),而另一半不等式用相似方法亦可證明。 | ||
|
||
<details><summary> Prove Lemma </summary> | ||
|
||
有興趣的讀者可以參考這篇 [Efficient Dynamic Programming Using Quadrangle Inequalities](https://dl.acm.org/doi/pdf/10.1145/800141.804691) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
這裡我就整段看不懂了QQQ
<details><summary> Prove Lemma </summary> | ||
|
||
有興趣的讀者可以參考這篇 [Efficient Dynamic Programming Using Quadrangle Inequalities](https://dl.acm.org/doi/pdf/10.1145/800141.804691) | ||
|
||
</details> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
這種如果是證明過程中 refer 出去的不需要用 <details> 包起來
不過你 refer 到論文有點@@
我會建議如果不難的話 至少用個幾句話給個淺顯的證明 或是提供一些直覺上會對的想法
|
||
\\[ | ||
\begin{array}{ccc} | ||
opt_{i-2,j-3} \le opt_{i-2,j-2} \le opt_{i-1,j-2}\\\\ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
既然 i - j = 0 代表 i == j 那 opt(i - 2, j - 3) 真的存在嗎?這是一個右界小於左界的case?
會發現前式轉移點的右界剛好是後式轉移點的左界!這樣一想,計算每個斜排時,最多只有 \\( O(N) \\) 種轉移來源,又約有 \\( 2N \\) 排,所以如果我們以索引值 \\(j-i\\) 由小到大遞增的順序計算 DP 表格,算出 DP 表格的複雜度 \\(O(N)\times O(2N) = O(N^2)\\),比直接算的 \\(O(N^3)\\) 快多了! | ||
|
||
但這樣做的正確性呢?若我們以索引值 \\(j-i\\) 由小到大遞增的順序計算,索引值差為 \\( j-i-1 \\) 的 \\( dp(i,j-1) \\) 與 \\( dp(i+1,j) \\) 會在算索引值差 \\( j-i \\) 的 \\( dp(i,j) \\) 前算出來,因此要算 \\( dp(i,j) \\) 時,\\( opt(i,j-1)、opt(i+1,j) \\) 都是已知,我們就不必再跑過所有轉移來源 \\([i,j]\\),只需要去檢查 \\( [opt(i,j-1), opt(i+1,j)] \\) 就能求得 \\(dp(i,j)\\) 與 \\(opt(i,j)\\)。 | ||
|
||
下圖中黑色格子為非法值,黃色已知,綠色為正在計算,灰色未計算,計算順序如箭頭所示。 | ||
|
||
<img src="image\Knuth_optimization\dp_order.png" width="300" style="display:block; margin: 0 auto;"/> | ||
|
||
\\[ 計算每塊綠色格子只需左邊與下方黃色格子的 opt\\] | ||
|
||
以下為程式碼片段 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
這一段也看不懂QQ
我懂覺得你的圖與你的敘述講得很像是在算某一條斜排的值上的每個元素只會使用到它左邊和下面的元素
但事實上其實是要 iterate from opt 表格上 他左邊的值 to opt 表格上他下面的值
|
||
<img src="image\Knuth_optimization\dp_order.png" width="300" style="display:block; margin: 0 auto;"/> | ||
|
||
\\[ 計算每塊綠色格子只需左邊與下方黃色格子的 opt\\] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
完全會被這句話帶歪
#38