【NOIP2018普及组】摆渡车
@擺渡車@
- @題目描述@
- @絕對不可能是正解的題解@
- @代碼 - 1@
- @看起來比較像正解的題解@
- @代碼 - 2@
- @End@
@題目描述@
有 n 名同學要乘坐擺渡車從人大附中前往人民大學,第 i 位同學在第 ti 分鐘去等車。只有一輛擺渡車在工作,但擺渡車容量可以視為無限大。擺渡車從人大附中出發、把車上的同學送到人民大學、再回到人大附中(去接其他同學),這樣往返一趟總共花費 m 分鐘(同學上下車時間忽略不計)。擺渡車要將所有同學都送到人民大學。
凱凱很好奇,如果他能任意安排擺渡車出發的時間,那么這些同學的等車時間之和最小為多少呢?
注意:擺渡車回到人大附中后可以即刻出發。
輸入
第一行包含兩個正整數 n,m,以一個空格分開,分別代表等車人數和擺渡車往返一趟的時間。
第二行包含 n 個正整數,相鄰兩數之間以一個空格分隔,第 i 個非負整數 ti代表第 i 個同學到達車站的時刻。
輸出
輸出一行,一個整數,表示所有同學等車時間之和的最小值(單位:分鐘)。
輸入樣例 1
5 1
3 4 4 3 5
輸入樣例 2
5 5
11 13 1 5 5
輸出樣例 1
0
輸出樣例 2
4
輸入輸出樣例 1 說明
同學 1 和同學 4 在第 3 分鐘開始等車,等待 0 分鐘,在第 3 分鐘乘坐擺渡車出發。擺渡車在第 4 分鐘回到人大附中。
同學 2 和同學 3 在第 4 分鐘開始等車,等待 0 分鐘,在第 4 分鐘乘坐擺渡車出發。擺渡車在第 5 分鐘回到人大附中。
同學 5 在第 5 分鐘開始等車,等待 0 分。
輸入輸出樣例 2 說明
同學 3 在第 1 分鐘開始等車,等待 0 分鐘,在第 1 分鐘乘坐擺渡車出發。擺渡車在第 6 分鐘回到人大附中。
同學 4 和同學 5 在第 5 分鐘開始等車,等待 1 分鐘,在第 6 分鐘乘坐擺渡車出發。擺渡車在第 11 分鐘回到人大附中。
同學 1 在第 11 分鐘開始等車,等待 2 分鐘;同學 2 在第 13 分鐘開始等車,等待 0 分鐘。他/她們在第 13 分鐘乘坐擺渡車出發。自此所有同學都被送到人民大學。總等待時間為 4。可以證明,沒有總等待時間小于 4 的方案。
數據規模與約定
對于 10% 的數據,n ≤ 10,m = 1,0 ≤ ti ≤ 100。
對于 30% 的數據,n ≤ 20,m≤ 2,0 ≤ ti ≤ 100。
對于 50% 的數據,n ≤ 500,m ≤ 100,0 ≤ ti ≤ 10^4。
另有 20% 的數據,n ≤ 500,m ≤ 10,0 ≤ ti ≤ 4×10^6。
對于 100% 的數據,n ≤ 500,m ≤ 100,0 ≤ ti ≤ 4×10^6。
@絕對不可能是正解的題解@
搜到了不少的題解,一個比一個強 orz。
這個算法應該是一個比較容易“想到”的算法(因為題目中很多的性質都沒有用到)
但是有用到斜率優化……
定義 a[i]a[i]a[i] 表示第 i 個時刻到達進行等車的人數。
定義 dp[i]dp[i]dp[i] 表示在第 i 個時刻發車,前面的同學最小等待時間之和。
則有:
dp[i]=min?(dp[j]+(∑k=j+1k≤ia[k]?(i?k)))(i?j>=m)dp[i] = \min(dp[j] + (\sum_{k=j+1}^{k\le i}a[k]*(i-k)))(i-j>=m)dp[i]=min(dp[j]+(k=j+1∑k≤i?a[k]?(i?k)))(i?j>=m)
拆開得到:
dp[i]=min?(dp[j]+i?(∑k=j+1k≤ia[k])?(∑k=j+1k≤ia[k]?k))(i?j>=m)dp[i] = \min(dp[j] + i*(\sum_{k=j+1}^{k\le i}a[k])-(\sum_{k=j+1}^{k\le i}a[k]*k))(i-j>=m)dp[i]=min(dp[j]+i?(k=j+1∑k≤i?a[k])?(k=j+1∑k≤i?a[k]?k))(i?j>=m)
令cnt[i]=∑j=1j≤ia[j]cnt[i]=\sum_{j=1}^{j\le i}a[j]cnt[i]=∑j=1j≤i?a[j],sum[i]=∑j=1j≤ia[j]?jsum[i]=\sum_{j=1}^{j\le i}a[j]*jsum[i]=∑j=1j≤i?a[j]?j。這兩貨可以前綴和O(n)處理。
則轉移方程式變為:
dp[i]=min?(dp[j]+i?(cnt[i]?cnt[j])?(sum[i]?sum[j]))=min?(dp[j]+i?cnt[i]?i?cnt[j]?sum[i]+sum[j])=min?((i?cnt[i]?sum[i])+(dp[j]+sum[j])?i?cnt[j])(i?j>=m)dp[i] = \min(dp[j] + i*(cnt[i]-cnt[j])-(sum[i]-sum[j]))\\=\min(dp[j] + i*cnt[i]-i*cnt[j]-sum[i]+sum[j])\\=\min( (i*cnt[i]-sum[i]) + (dp[j]+sum[j]) - i*cnt[j]) (i-j>=m)dp[i]=min(dp[j]+i?(cnt[i]?cnt[j])?(sum[i]?sum[j]))=min(dp[j]+i?cnt[i]?i?cnt[j]?sum[i]+sum[j])=min((i?cnt[i]?sum[i])+(dp[j]+sum[j])?i?cnt[j])(i?j>=m)
令 f(i)=(i?cnt[i]?sum[i]),g(j)=(dp[j]+sum[j]),h(j)=cnt[j]f(i)=(i*cnt[i]-sum[i]), g(j)=(dp[j]+sum[j]), h(j)=cnt[j]f(i)=(i?cnt[i]?sum[i]),g(j)=(dp[j]+sum[j]),h(j)=cnt[j]。
則 dp[i]=min?(f(i)+g(j)?i?h(j))(j<=i?m)dp[i]=\min(f(i) + g(j) - i*h(j)) (j<=i-m)dp[i]=min(f(i)+g(j)?i?h(j))(j<=i?m)。
典型的不能再典型的斜率優化式…… i 和 h(j) 還具有單調性……
@代碼 - 1@
雖然當初我去都沒去普及組。
不過普及組(涉嫌)考到斜率優化倒是令我極其感興趣,就寫了一下 qwq。
@看起來比較像正解的題解@
考慮到n, m如此之小,我們以它們倆作為狀態進行 dp。
首先有這樣一個比較關鍵的性質:車輛停留的時間不會超過 m ,否則它可以往返一次再回來,這樣不會影響后面的狀態且有可能更優秀。
先按到達時間給人排序。然后定義狀態 dp[i][j]dp[i][j]dp[i][j] 表示第 i 個人等了 j 分鐘,前 i 個人的最小等待時間和。因為上面那個性質,有 j <= 2*m。抵到上界的唯一情況 t[i] = t[i-1],且轉移時于 t[i-1] 時刻發車,回來停留 m 分鐘。
根據狀態定義,可以得到轉移方程:
(1)dp[i][j]=min?(dp[i?1][k]+j)(t[i?1]+k=t[i]+j)(2)dp[i][j]=min?(dp[i?1][k]+j)(t[i?1]+k+m<=t[i]+j)(1)dp[i][j] = \min(dp[i-1][k] + j)(t[i-1]+k=t[i]+j)\\(2)dp[i][j] = \min(dp[i-1][k] + j)( t[i-1] + k + m <= t[i] + j )(1)dp[i][j]=min(dp[i?1][k]+j)(t[i?1]+k=t[i]+j)(2)dp[i][j]=min(dp[i?1][k]+j)(t[i?1]+k+m<=t[i]+j)
對于(1),第 i 個人與第 i-1 個人同車。
對于(2),第 i 個人與第 i-1 個人不同車。
以上都要滿足 0 <= j, k <= 2*m,1<=i<=n。
現在算法時間復雜度為 O(n*m^2) ,雖然已經足以通過此題,但是還可以做到更優秀。
第(1)類轉移是O(1)的,不去管它。
第(2)類轉移,變換條件得到:k <= t[i]+j-t[i-1]-m。可以用前綴最小值快速求解。
時間復雜度O(n*m)。以及代碼復雜度比上面那個斜率優化不知道高到哪里去了。
@代碼 - 2@
考場上同學們好像做得很炸……
不過分析下來其實難點也不算多。只是可能狀態定義不太好想。
@End@
就是這樣,新的一天里,也請多多關照哦(ノω<。)ノ))☆.。
總結
以上是生活随笔為你收集整理的【NOIP2018普及组】摆渡车的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【NOIP2018普及组】【DP】摆渡车
- 下一篇: 【NOIP2018普及组】摆渡车 题解