題解 P1622 釋放囚犯
題面
題目描述
Caima 王國中有一個奇怪的監獄,這個監獄一共有 P 個牢房,這些牢房一字排開,第 i 個緊挨著第 i + 1 個(最後一個除外)。現在正好牢房是滿的。
上級下發了一個釋放名單,要求每天釋放名單上的一個人。這可把看守們嚇得不輕,因為看守們知道,現在牢房中的 P 個人,可以相互之間傳話。如果某個人離開了,那麼原來和這個人能說上話的人,都會很氣憤,導致他們那天會一直大吼大叫,搞得看守很頭疼。如果給這些要發火的人吃上肉,他們就會安靜點。
輸入格式
第一行兩個整數 P 和 Q,Q 表示釋放名單上的人數;
第二行 Q 個整數,表示要釋放哪些人,保證按遞增的順序給出。
輸出格式
僅一行,表示最少要給多少人次送肉吃。
樣例 #1
樣例輸入 #1
1 | 20 3 |
樣例輸出 #1
1 | 35 |
提示
樣例說明 #1
先釋放 14 號監獄中的罪犯,要給 1 到 13 號監獄和 15 到 20 號監獄中的 19 人送肉吃;再釋放 6 號監獄中的罪犯,要給 1 到 5 號監獄和 7 到 13 號監獄中的 12 人送肉吃;最後釋放 3 號監獄中的罪犯,要給 1 到 2 號監獄和 4 到 5 號監獄中的 4 人送肉吃。
資料規模與約定
- 對於 50% 的資料,1 ≤ P ≤ 100,1 ≤ Q ≤ 5;
- 對於 100% 的資料,1 ≤ P ≤ 103,1 ≤ Q ≤ 100,Q ≤ P,保證釋放的人所在的牢房編號按遞增的順序給出。
思路
題意即求釋放列表中所有罪犯的費用之和最小,每次釋放,罪犯i到他兩邊空牢房之間的所有人,都需要消耗一塊肉。每次釋放一個罪犯,可以想到區間
DP,狀態 f[l][r]
表示從l到r號罪犯全部釋放所需要消耗的肉塊總數。
之後思考狀態轉移方程。要求最小值,f[l][r] 初始值
INT_MAX。f[l][r] = min of f[l][m-1] + f[m+1][r] + Pos[r+1] - Pos[l-1] -2
,其中 m 屬於區間
[l,r],列舉合併點,即此次釋放的罪犯,罪犯兩側到l和r號罪犯的消耗f[l][m-1]和f[m+1][r]。Pos[i]定義i號罪犯的編號。這裡其實是一種反向的思路,m點應該是最先釋放的(?Pos[r+1] - Pos[l-1] -2即此區間兩側最近的罪犯之間的人數,減去區間兩端。即區間合併的額外費用。注意要在Pos陣列中定義Pos[Q+1]=N+1。
程式碼
1 |
|
小結
本題難點在於建模,區間DP部分比較典型。