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
xxxxxxxxxx
資訊之芽第八週—動態規劃(二)
tags:
資訊之芽
tags:
2021暑期筆記
這兩週真是風風雨雨,首先第一週是段考週,所以有很多時間拿去惡補段考。第二週則是疫情關係要在家裡線上上課
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →上課內容
一堆的背包問題(真的很多種耶)
01背包問題
無限背包問題
有限背包問題
混合背包問題
二維背包問題
分組背包問題
背包合併
背包問題變化
分數背包
不同做法複雜度
上機作業
背包問題主要有三個變量:價值、重量、物品數量,因此可以有三個作法:
高棕櫚農場
題目連結
這一題不能用重量做,因為重量的範圍可以到\(10^5\),因此只能用價值來做
有一個要點,無限大可以memset定義為0x3f3f3f3f,以十進位表示1061109567,在int的範圍但不會超過
定義
定義\(f(n,m)\)為取n樣物品,價值恰為m,重量總和最小值
轉移方式
\(f(n,m) = min(f(n-1,m), f(n-1,m-v_n)+w_n), m ≧ v_n\)
\(f(n,m) = f(n-1,m), m < v_n\)
邊界條件
f(0,0) = 0, f(0,k) = INF (k>0)$
因為取零樣物品價值要k不可能達到,因此重量設為無限大
我們可以藉由滾動dp來節省空間,壓成一維(跟用重量作為狀態一樣)
最後,在從dp裡面取出max(k), for all f(N,k) ≦ W
程式碼
高棕櫚農場2
題目連結
有些細節是必須要注意的,也就是初始化的細節。
背包問題是否恰好裝滿
對於原本初始化dp[0] = 0,代表對於重量限制為0的背包價值最高為0
接下來有兩種情況需要討論,第一種是重量限制為w的背包最多的價值
1. 恰好裝滿
此時必須初始化dp[i] = -INF,是因為要恰好裝滿的關係,初始化的dp 數組事實上就是在沒有任何物品可以放入背包時的合法狀態,其他除了0之外容量的背包均沒有合法的解,屬於未定義的狀態,所以都應該被賦值為 −∞ 。當前的合法解,一定是從之前的合法狀態推得的(−∞跟−∞取max還是−∞)
2. 不需恰好裝滿
如果背包並非必須被裝滿,那麼任何容量的背包都有一個合法解“什麼也不裝”,這個解的價值為0,所以初始化時狀態的值也就全部為0了。
如果來看轉移式,\(dp[j] = max(dp[j],dp[j-weight[i]]+val[i])\),如果兩者的狀態都屬於未定義,對於需恰好裝滿的狀況,兩者都是−∞,表示沒有合法的狀態可以構成此重量。同時,如果不需恰好裝滿的情況,即使\(dp[j]\)和\(dp[j-weight[i]]\)都未定義(等於0),還是可以被更新(在沒有裝滿的情況下,dp[j] = val[i])
這一題除了以上發現,還有一個很重要的東西,就是迴圈到底要放哪一層的問題。主要是卡在 for(int p=1;p<=k;p++)到底要放在哪一層的問題,結果是要放在第三層。
問題一:dp[j][p]取決於dp[j][p] 和dp[j-weight[i]][p-1],而且對於一個物品最多只能放一次,如果放在第二層,dp[j-weight[i]][p-1] 就已經被更新過了,有可能已經取了第 i 樣物品會有重複取的問題,如果放在第三層,代表對每一種不同的重量先更新放入幾樣物品的1到k,再更新重量,這樣就可以保證dp[j][p]不會取到已經更新的格子(dp[j][p] 沒被更新、dp[j-weight[i]][p-1] 其中第一維的j-weight[i] 也還沒被更新)
問題二:p要從1到k還是k到1,這其實都可以,因為要取的格子不管從前往後或後往前取都只會取到上一輪(i-1) 的更新東西,因此不影響。還有,因為是定義最多取p樣物品,所以無論i為多少,每一次p皆要更新的k(如果k=5,取一樣物品也符合情況)
定義
定義\(f(j,p)\)看完 i 樣物品後,重量限制為j,最多取p樣物品的最大價值
轉移方式
\(dp[j][p] = max(dp[j][p],dp[j-weight[i]][p-1]+val[i])\)
邊界條件
\(dp[i][j] = 0\) (for all elements in dp)
玩電梯
題目連結
題目連結2
這一題要用到3個重要的技巧:前綴和、差分、滾動dp
差分在某一次手寫作業有寫到,不過那時候沒有很注意這個部分就是了
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →差分
差分是前綴和的逆運算,也就是說,把兩項的差算出來就是差分。定義如下:
\[b_i = \begin{cases}a_i-a_{i-1}, &\text{if }i\gt 1 \\a_1, & \text{if } i = 1\end{cases}\]
差分的使用時機是區間加值,一個區間內的數字都加上一個定值,這時候就可以使用到差分的技巧。使用方式如下,當我要在區間 \([l,r]\) 的每一個數字都加上一個值\(v\),以下步驟:
第二步驟可以重複好幾次做,這樣複雜度從原本的\(O(n)\)就變成了O(1)了!
這一題使用到差分的技巧,讓原本的\(O(kn^2)\)減少成\(O(kn)\),然後就可以過了!
定義
定義 \(dp[i][j]\) 為第 i 次走到樓層j的方法數
轉移式
這題如果用拉的比較不好想,所以改用推的試試看
\(dp[i+1][j] = dp[i+1][j]+dp[i][p],\) for \(j\in[p-r],[p+1,p+r],r = |p-b|-1\)
邊界條件
\(dp[0][a] = 1\)
轉移式比較複雜一點,不過可以用差分優化搭配前綴和把原本\(O(n)\)的時間降到\(O(1)\)
從這一題可以發現到,用拉的和用推的有不同的使用時機,可以以思考方式比較清楚的想法去想轉移式。
取名字好困難QQ
題目連結

跟題目一樣,我覺得要通靈才能想到這一題的作法!
結果是問了別人才大概感受到這一種作法!!!
我們既然不知道到底一個數字要不要乘2,我們可以透過做LIS的過程來做決定。當我們把乘與2之後的數字跟原本數字一起push進去,就可以發現到LIS不可能同時取到2個數字。利用這個方法就可以用LIS的過程決定一個數字到底應該要變2倍還是不用。
要找到最長的非嚴格遞增序列,最大的差別就是要把原本的lower_bound改成upper_bound。一整天想一題的感覺超級糟糕
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →手寫作業
這一週是講歸約法,作業如下:


這一週手寫作業的狀況還不錯,71/75,不過第一題是緊急向別人求救才把答案改掉
原本是寫B,後來改A,原因有以下兩點:
所以A是錯誤的!

下面是解答的畫法,其實跟我蠻像的XDD