题目链接
1010: [HNOI2008]玩具装箱toy
Time Limit: 1 Sec
Memory Limit: 162 MB
Submit: 7027
Solved: 2670
[ Submit][ Status][ Discuss]
Description
P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京。他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中。P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的。同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一个容器中,那么容器的长度将为 x=j-i+Sigma(Ck) i<=K<=j 制作容器的费用与容器的长度有关,根据教授研究,如果容器长度为x,其制作费用为(X-L)^2.其中L是一个常量。P教授不关心容器的数目,他可以制作出任意长度的容器,甚至超过L。但他希望费用最小.
Input
第一行输入两个整数N,L.接下来N行输入Ci.1<=N<=50000,1<=L,Ci<=10^7
Output
Sample Input
5 4
3
4
2
1
4
Sample Output
1
题解:用dp[i]表示装完前i个物品的最小花费,转移就是:
dp[i]=min(dp[k]+(sum[i]-sum[k]+i-k-1-l)*(sum[i]-sum[k]+i-k-1-l))
sum[i]表示前i个物品的前缀和。
方法一:
另w(k,i)=(sum[i]-sum[k]+i-k-1-l)*(sum[i]-sum[k]+i-k-1-l);
可以证明:w(i,j)+w(i+1,j+1)<=w(i,j+1)+w(i+1,j)。
另k(i)表示状态i取到最优值时的决策,则:k(i)<=k(j)。决策单调。
因此我们可以采用论文:《1D/1D动态规划优化初步》中的方法。
O(nlgn)解决此问题。代码如下:
#include
#include
#include
#include
方法二:再来分析转移方程:
dp[i]=min(dp[k]+(sum[i]-sum[k]+i-k-1-l)*(sum[i]-sum[k]+i-k-1-l))
=min(dp[k]+(sum[i]+i-l-1)*(sum[i]+i-l-1)+(sum[k]+k)*(sum[k]+k)-2*(sum[i]+i-l-1)*(sum[k]+k))
=min( dp[k]+(sum[k]+k)*(sum[k]+k)-2*(sum[i]+i-l-1)*(sum[k]+k) ) + (sum[i]+i-l-1)*(sum[i]+i-l-1)
我们令常量 P=(sum[i]+i-l-1)
令:X(k)=dp[k]+(sum[k]+k)*(sum[k]+k)
令:Y(k)=(sum[k]+k)
则:dp[i]=min(X(k)-2*P*Y(k))+p*p;
令C=X(k)-2*P*Y(k) ,则:
Y(k)=1/2p*X(k) - C/2*p;
我们可以把决策K看成是二维坐标上的一个点( X(k),Y(k) ) ,求解dp[i]可以看成是,一条斜率固定的直线,在一些点中(决策),找一个点,使得纵坐标的截距最大即(C最小)。不难发现,这个点一定在这些点的凸包上。
由于1/2*p随着i的增加单调递减,X(k)随着K的增加单调递增。
因此我们可以用一个双端队列维护凸包上的点,队列中相邻两点的斜率随着x的增加而减少。
每次转移的时候,从队首开始,找到第一个与后一个点的斜率小于当前直线的斜率的点,就是我们要找的决策点。对于不满足条件的点出队。
转移完成以后,从队尾开始添加一个点,保证队列中的点斜率递减,不满足条件的点出队。
这样就可以均摊O(1)复杂度,实现转移。
对于斜率优化的具体内容可看论文:《1D/1D动态规划优化初步》,或者其它关于斜率优化的论文。
代码如下:
#include
#include
#include
#include
#include
#include
#include
#include