玩具裝箱TOY 斜率優化DP

2022-05-19 06:28:50 字數 3547 閱讀 6368

《更新提示》

《第一次更新》

《正文》

p教授要去看奧運,但是他捨不下他的玩具,於是他決定把所有的玩具運到北京。他使用自己的壓縮器進行壓縮,其可以將任意物品變成一堆,再放到一種特殊的一維容器中。p教授有編號為 \(1. . .n\) 的 \(n\) 件玩具,第 \(i\) 件玩具經過壓縮後變成一維長度為 \(c_i\)​ .為了方便整理,\(p\)教授要求在乙個一維容器中的玩具編號是連續的。同時如果乙個一維容器中有多個玩具,那麼兩件玩具之間要加入乙個單位長度的填充物,形式地說如果將第 \(i\) 件玩具到第 \(j\) 個玩具放到乙個容器中,那麼容器的長度將為 \(x=j-i+\sum_^jc_k\)​ 製作容器的費用與容器的長度有關,根據教授研究,如果容器長度為 \(x\) ,其製作費用為 \((x-l)^2\) .其中 \(l\) 是乙個常量。\(p\)教授不關心容器的數目,他可以製作出任意長度的容器,甚至超過 \(l\) 。但他希望費用最小.

第一行輸入兩個整數\(n\),\(l\).接下來n行輸入\(c_i\).\(1<=n<=50000,1<=l,c_i<=10^7\)

輸出最小費用

5 434214

1
簡單分析題目大意:給定乙個數列,可以將其分為若干個連續的子段,將區間\([i,j]\)分為一段的花費為\((j-i+\sum_^jc_k-l)^2\),求最小劃分總花費。

由於沒有需要劃分多少段的限制,可以直接簡單地設定狀態:f[i]代表完成了前i個數的劃分的最小花費和。

區間的花費是利用字首和可以o(1)求解的,那麼狀態轉移方程就是$$f_i=min$$

暴力思路:\(o(n^2)\)列舉\(i,j\)求解。

但是\(50000\)的資料\(o(n^2)\)肯定不行啊,我們考慮優化這個dp。

先化簡括號內花費內容:

\[(i-(j+1)+sum_i-sum_j-l)^2

\\=(i-j-1+sum_i-sum_j-l)^2

\\=((i+sum_i)+(-l-1-j-sum_j))^2

\\設a_k=(k+sum_k),b_k=(a_k+l+1)

\\=(a_i-b_j)^2

\]代回原式:

\[f_i=min\

\]假設我們已經找到了最優的\(f_j\),那麼:

\[f_i=f_j+(a_i-b_j)^2

\\⇒f_i=f_j+a_i^2-2a_ib_j+b_j^2

\\⇒f_j+b_j^2=2a_ib_j+(f_i-a_i^2)

\](將只與i有關的項和只與j有關的項分別整理)

這個時候我們發現式子中有一項是即和\(i\)有關有和\(j\)有關的,然後就可以做一些神奇的優化了。

我們視\(f_j+b_j^2\)為\(y\),\(b_j\)為\(x\),\(2a_i\)為\(k\),\((f_i+a_i^2)\)為\(b\),那麼我們就可以把它當做乙個一次函式的的表示式\(y=kx+b\)。而且這個一次函式需滿足:

1.過定點\((b_j,f_j+b_j^2)\),由於這個點只和\(j\)有關,稱其為\(p_j\)

2.其斜率為\(2a_i\)

這時候,我們需要重新定義\(f_i\)的含義:滿足兩個要求的一次函式的截距\((b)\)加上\(a_i^2\)

由於\(a_i^2\)的值是確定的,我們需要求最小的\(f_i\),即求做小的一次函式的截距。

我們將滿足斜率為\(2a_i\)的直線以及點\(p_1,p_2,...,p_j\)描述在圖中:

直線自下向上移動,只要它過任何乙個點\(p\),它就成為了符合要求的直線。

我們要求截距最小,顯然,當它自下向上移動過的第乙個點\(p_j\)時,截距最小。如圖,此時能取得截距最小的點是\(p_2\)。那麼由上可知,\(j=2\)時,一次函式的截距最小,更新得到的\(f_i\)也是最小的。

所以,我們的目標就轉變為了找到一次函式能夠第乙個「碰到」的點。

觀察上圖,我們將最有可能與直線先「碰到」的點(最外圍的點)兩兩相連,發現:它們近似的構成了乙個下凸殼的形狀,兩兩相連的線段所在的直線的斜率依次遞增

此時我們發現了乙個很好的性質,我們的目標直線第乙個過的點最優點\(p_j\)滿足:\(p_j,p_\)所在直線是斜率大於目標直線斜率的第一條直線。(\(p_2,p_3\)構成的直線的斜率大於圖中直線的斜率,但\(p_1,p_2\)構成的直線的斜率小於圖中直線的斜率,所以\(p_2\)為最優點)

那麼這就成為了我們的突破口了:由於構成下凸殼直線滿足斜率單調遞增,我們用單調佇列維護這些\(p\)點。由於隨著i的增加,\(a_i\)也是單調遞增的,這就應和了單調佇列的操作。

對於每乙個\(i\),我們讓斜率小於\(2a_i\)的單調佇列中的直線所對應的點出隊(它小於當前的\(2a_i\),由於\(a_i\)單調遞增,它也一定小於以後的\(2a_i\),所以這些點將會是一直無用的,可以直接出隊),直到找到第一條斜率大於\(2a_i\)的直線,此時,隊頭的點的編號j即為最優決策。我們直接利用該決策轉移。

完成轉移以後,新的點\(p_i\)也需要加入佇列裡,此時,我們還要維護乙個操作:

當\(p_i\)(圖中的\(p_7\))加入後,我們發現,原來的\(p_4,p_3\)構成的直線的斜率大於\(p_3\)和新的\(p_4\)構成的斜率,這樣,\(p_4\)就到了內部,新的下凸殼由\(p_1,p_2,p_3,p_7\)構成,我們需要讓\(p_4\)出隊。

即當\(slope(q[tail],q[tail-1])>slope(q[tail-1],i)\)(\(slope\)代表斜率函式)時,隊尾出隊。

事實上,我們在不斷維護乙個下凸殼的形狀,由於單調佇列一共會進出至多n個點,所以,這樣實現轉移的時間複雜度是\(o(n)\)的,我們將此種優化方法稱為斜率優化。

\(code:\)

#includeusing namespace std;

const int n=50000+80;

long long f[n],q[n],sum[n],toy[n],n,l,head,tail;

inline long long a(long long k)

inline long long b(long long k)

inline long long x(long long k)

inline long long y(long long k)

inline double slope(long long p,long long q)

int main(void)

for(int i=1;i<=n;i++)

printf("%lld\n",f[n]);

}

《後記》

斜率優化DP 玩具裝箱

hnoi2008 玩具裝箱toy time limit 1000ms memory limit 165536k total submit 5 accepted 5 description p教授要去看奧運,但是他捨不下他的玩具,於是他決定把所有的玩具運到北京。他使用自己的壓縮器進行壓縮,其可以將任意...

BZOJ1010 玩具裝箱toy(斜率優化)

p教授要去看奧運,但是他捨不下他的玩具,於是他決定把所有的玩具運到北京。他使用自己的壓縮器進行壓縮,其可以將任意物品變成一堆,再放到一種特殊的一維容器中。p教授有編號為1.n的n件玩具,第i件玩具經過壓縮後變成一維長度為ci.為了方便整理,p教授要求在乙個一維容器中的玩具編號是連續的。同時如果乙個一...

HNOI2008 玩具裝箱TOY(斜率優化)

題目鏈結 題意 有編號為 1 cdots n 的n件玩具,第 i 件玩具經過壓縮後變成一維長度為 c i 要求在乙個容器中的玩具編號是連續的,同時如果將第 i 件玩具到第 j 個玩具放到乙個容器中,那麼容器的長度將為 x j i sum limits c k 如果容器長度為 x 其製作費用為 x l...