WiwiHo
https://hackmd.io/@wiwiho/crc1082algo
https://tg.pe/xgaG
Divide and Conquer
把一個問題分成多個部分
對每個部分分別求解後
再求出全部的解
先將數列砍成兩半
求在兩邊的逆序數對
順便把兩邊由大到小排序好
再求跨越兩邊的
遞迴處理
如果兩邊都先排序好了
在同一邊的東西的相對位置可能改變
但在不同邊的不變
Note: 畫圖
\(S_i=\sum_{k=1}^i a_k\)
並且令 \(S_0=0\)
\(\sum_{k=l}^r a_k=\sum_{k=1}^r a_k - \sum_{k=1}^{l-1} a_k=S_r-S_{l-1}\)
\(D_i=a_i-a_{i-1}\)
並且令 \(a_0=0\)
將 \(a_l,a_{l+1},...,a_r\) 加上 \(v\)
\(D\) 的變化:
\(\Rightarrow\) 變成單點修改
Dynamic Programming
遞迴?
有好多子問題是重複的
把已經算過的存下來
Note:
例如費氏數列的 \(f(1)\)、\(f(2)\)、\(f(3)\)……
這些存下來的東西稱為狀態
top-down 用在狀態數多但很多沒有用的狀況
但遞迴的常數大
所以幾乎所有狀態都有用時
用 bottom-up 比較好
\(dp[i][j]=\) 第 \(i\) 天做活動 \(j\) 時最少要休息幾天
如果第 \(i\) 天不能做活動 \(j\)
則 \(dp[i][j]=\infty\),否則
\(dp[0][0] = 0\)
按 \(n\) 從小到大計算
\(\min\{dp[n][0],dp[n][1],dp[n][2]\}\)
狀態數 \(\times\) 轉移複雜度
\(O(n) \times O(1)=O(n)\)
\(dp[l][r]=\) 將第 \(l\) 隻到第 \(r\) 隻史萊姆
合併成一隻需要的最少成本
第 \(l\) 隻到第 \(r\) 隻史萊姆合起來的大小
\(\sum_{k=l}^r a_k\)
記作 \(s[l][r]\)
\(dp[l][r]=\min\{dp[l][k] + dp[k+1][r] + s[l][k] + s[k+1][r] | l \leq k < r\}\)
從 \(r-l\) 小的做到大的
\(dp[i][i]=0\)
\(dp[1][n]\)
轉移:\(O(n)\)
狀態數:\(O(n^2)\)
\(\Rightarrow O(n^3)\)
\(dp[i][j]\) 是將前 \(i\) 種物品中的一些放進背包
且總體積不超過 \(j\) 時的最大總價值
前 \(i\) 種物品中的一些放入背包
等同於將前 \(i-1\) 種物品中的一些放入背包
再放入或不放入第 \(i\) 種物品
\(dp[i][j]=\begin{cases} \max(dp[i-1][j-w_i] + v_i, dp[i-1][j]), & \quad \text{if }j \geq w_i \\ dp[i-1][j], & \quad \text{otherwise} \end{cases}\)
\(dp[0][j]=0\)
\(i\) 由小到大、\(j\) 由小到大
轉移:\(O(1)\)
狀態數:\(O(nm)\)
\(\Rightarrow O(nm)\)
等等講
和 0/1 背包一樣
改一下轉移式?
將前 \(i\) 種物品中的一些放入背包
等同於將前 \(i-1\) 種物品中的一些放入背包
再不放入或放入若干個第 \(i\) 種物品
\(dp[i][j]=\max\{dp[i-1][j-kw_i]+kv_i | 0 \leq j-kw_i, k \in \mathbb{N}_0\}\)
轉移複雜度:\(O(m)\)
有點太大
也可以說成是
「將前 \(i-1\) 種物品中的一些放入背包
再放入一個第 \(i\) 種物品」
或「將前 \(i\) 種物品中的一些放入背包
再放入一個第 \(i\) 種物品」
\(dp[i][j]=\begin{cases} \max(dp[i-1][j-w_i]+v_i, dp[i][j-w_i]+v_i, dp[i-1][j]), & \quad \text{if } j \geq w_i\\ dp[i-1][j], & \quad \text{otherwise} \end{cases}\)
由於 \(dp[i][j-w_i] \geq dp[i-1][j-w_i]\)
\(dp[i][j]=\begin{cases} \max(dp[i][j-w_i]+v_i, dp[i-1][j]), & \quad \text{if } j \geq w_i\\ dp[i-1][j], & \quad \text{otherwise} \end{cases}\)
轉移複雜度:\(O(1)\)
把同一種的 \(c_i\) 個物品
視為 \(c_i\) 種只有一個的物品
然後用 0/1 背包做
物品數:\(\sum c_i\)
時間複雜度:\(O(m\sum c_i) \geq O(nm)\)
把同一種的 \(c_i\) 種物品分成 \(O(\log c_i)\) 種
總數要是 \(c_i\)
分法:
找到最大的 \(x\)
滿足 \(2^x-1 \leq c_i\)
分成數量分別是 \(1,2,4,...,2^{x-1}\) 的 \(x\) 種
總數是 \(2^x-1\)
再有一種的數量是 \(c_i-(2^x-1)\)
\(1,2,4,...,2^x\)
可以湊出 \([0,2^x-1]\) 的所有數字
加上 \(c_i-(2^x-1)\)
可以湊出 \([c_i-(2^x-1), c_i]\) 的所有數字
聯集:\([0,c_i]\)
分割後
把同一種的物品壓成只有一個
用 0/1 背包做
物品種數:\(O(\sum \log c_i)\)
時間複雜度:\(O(m \sum \log c_i)\)
背包問題的空間複雜度都和狀態數相同
狀態數:\(O(nm)\)
但是看看轉移式
\(dp[i][j]=\begin{cases} \max(dp[i-1][j-w_i] + v_i, dp[i-1][j]), & \quad \text{if }j \geq w_i \\ dp[i-1][j], & \quad \text{otherwise} \end{cases}\)
算 \(dp[i][j]\) 只會用到 \(dp[i-1][...]\)
\(\Rightarrow\) 有些狀態過一陣子就沒用了
把不用的狀態丟掉
\(\Rightarrow\) 滾動陣列
把 \(dp\) 看成二維表格
在計算某一列時只會用到它的上一列
所以從第一列做到最後一列
算完某一列後就可以把上一列丟掉
\(dp[s]=\) 集合 \(s\) 是否滿足條件
\(dp[s]=\max\{dp[s-S_i] | S_i \subset s\}\)
\(dp[0]=1\)
時間複雜度: $\(O(m2^n)\)
or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Do you want to remove this version name and description?
Syncing