1. 程式人生 > >USACO16FEB 再探圓形穀倉(斜率優化DP)

USACO16FEB 再探圓形穀倉(斜率優化DP)

題意

n n 個順時針排列的牛棚,可以開 k k 個口讓牛順時針進入,已知每個牛棚需要多少隻牛,問所有牛在牛棚內行走的距離總和最小值。
1

n 100 1 \leq n \leq 100
1 k
7 1 \leq k \leq 7

思路

序列倍長,斷環成鏈,區間轉移,線性動歸,這種套路實在見得多了,不難打出一個 n 3 n^3 d

p dp 如下:

FOR(r,0,n-1)
{
	FOR(i,1,n)cnt[i]=cnt[i-1]+a[r+i],sum[i]=sum[i-1]+a[r+i]*i;
	memset(dp,0x3f,sizeof(dp));
	dp[0][0]=0;
	FOR(i,1,K)
		FOR(j,1,n)
			FOR(k,0,j-1)
				dp[i][j]=min(dp[i][j],dp[i-1][k]+(sum[j]-sum[k])-(k+1)*(cnt[j]-cnt[k]));
	ans=min(ans,dp[K][n]);
}

現在優化掉其中一維即可,顯然是轉移的那一維,列出轉移式:
d p i , j = min { d p i 1 , k + ( s u m j s u m k ) + ( k + 1 ) ( c n t k c n t j ) } , k [ 0 , j 1 ] dp_{i,j}=\min\{dp_{i-1,k}+(sum_j-sum_k)+(k+1)(cnt_k-cnt_j)\},k\in[0,j-1]
把和 j j 有關或常數提出來,將只和 k k 有關、與 j , k j,k 有關的分別並列得到:
d p i , j = min { d p i 1 , k s u m k + c n t k ( k + 1 ) c n t j ( k + 1 ) } + s u m j , k [ 0 , j 1 ] dp_{i,j}=\min\{dp_{i-1,k}-sum_k+cnt_k(k+1)-cnt_j(k+1)\}+sum_j,k\in[0,j-1]
X i = i + 1 , Y i , j = d p i , j s u m j + c n t j ( j + 1 ) , K i = c n t i , C i = s u m i X_i=i+1,Y_{i,j}=dp_{i,j}-sum_j+cnt_j(j+1),K_i=cnt_i,C_i=sum_i
原式又變成 d p i , j = min { Y i 1 , k K j X k } + C j dp_{i,j}=\min\{Y_{i-1,k}-K_jX_k\}+C_j
維護一個 ( X k , Y i 1 , k ) (X_k,Y_{i-1,k}) 的下凸包,即保證斜率一定時, y y 軸上截距最小,而斜率的 K i K_i 又是單調遞增的,那斜率優化就顯然了。
總結一下斜率是如何優化 D P DP 的。
回到我們的單調佇列優化 D P DP d p i = min { F j } + G i dp_i=\min\{F_j\}+G_i max \max 相同。
其中 F j F_j 是僅與 j j 相關的函式, G i G_i 是隻與 i i 相關的函式,維護一個關於 F j F_j 的單調佇列即可。
而當出現了