BZOJ_1010_[HNOI2008]_玩具装箱toy_(斜率优化动态规划+单调队列)

Posted 晴歌。

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ_1010_[HNOI2008]_玩具装箱toy_(斜率优化动态规划+单调队列)相关的知识,希望对你有一定的参考价值。

描述


http://www.lydsy.com/JudgeOnline/problem.php?id=1010

给出\\(n\\)和\\(l\\).有\\(n\\)个玩具,第\\(i\\)个玩具的长度是\\(c[i]\\),要求将玩具分成若干段,从\\(i\\)到\\(j\\)分为一段的长度为\\(x=j-i+\\sum_{k=i}^jc[k]\\),费用为\\((x-l)^2\\).求最小费用.

 

分析


用\\(dp[i]\\)表示前\\(i\\)个玩具所需的最小费用,则有$$dp[i]=min\\{dp[j]+(sum[i]-sum[j]+i-(j+1)-l)^2(1<=j<i)\\}$$

其中\\(sum[i]\\)表示的是\\(c[i]\\)的前缀和.

为了方便,我们设$$A[i]=sum[i]+i,l=l+1$$

于是原方程久等价于$$dp[i]=min\\{dp[j]+(A[i]-A[j]-l)^2(1<=j<i)\\}$$

我们设\\(j<k<i\\)且在计算\\(dp[i]\\)的时候,决策\\(k\\)更优.也就是说$$dp[k]+(A[i]-A[k]-l)^2<dp[j]+(A[i]-A[j]-l)^2$$

在纸上写写画画,把式子打开再遍一下形,容易得到$$\\frac{[dp[k]+(A[k]+l)^2]-[dp[j]+(A[j]+l)^2]}{2\\times{A[k]}-2\\times{A[j]}}<A[i]$$

是不是很像$$\\frac{Y_k-Y_j}{X_k-X_j}$$的形式?

这玩意儿不就是斜率吗?!我们设它为\\(g(k,j)\\)

我们可以发现\\(A[i]\\)是单调递增的,所以所有决策可以转化为二维空间上的点集.

也就是说\\(k\\)这个点和\\(j\\)这个点的连线的斜率如果小于\\(A[i]\\),那么\\(k\\)这个决策就更优.

那么对于三个决策\\(a<b<c\\),如果有\\(g(c,b)<=g(b,a)\\),那么\\(b\\)决策一定不会被选中.为什么呢?我们来讨论一下(对于任意\\(3<i<=n\\)):

1.如果\\(g(b,a)<A[i]\\),那么必有\\(g(c,b)<A[i]\\),也就是\\(c\\)最优,选择决策\\(c\\).

2.如果\\(g(b,a)>=A[i]\\),那么\\(b\\)不是最优,最优可能是\\(a\\)或\\(c\\).

所以我们在新加入一个点的时候,就可以把它看作\\(c\\),然后把所有这样的\\(b\\)都去掉,直到\\(g(c,b)>g(b,a)\\),所以我们需要处理的斜率是单调递增的.

由于\\(A[i]\\)是单调递增的,所以对于任意的\\(i<n\\),如果满足上面的不等式,那么对于任意的\\(i\',i<i<=n\\),由于\\(A[i\']>A[i]\\),所以上不等式仍然成立,所以\\(i\'\\)的最优决策的位置一定不比\\(i\\)的最优决策小.

这样我们就可以用一个单调队列分别维护队首和队尾啦.

 

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long ll;
 5 const int maxn=50000+5;
 6 ll n,l,front,tail;
 7 ll sum[maxn],A[maxn],dp[maxn],q[maxn];
 8 inline ll pow_(ll x){ return x*x; }
 9 inline ll up(int k,int j){ return dp[k]-dp[j]+pow_(A[k]+l)-pow_(A[j]+l); }
10 inline ll dn(int k,int j){ return 2*(A[k]-A[j]); }
11 int main(){
12     scanf("%lld%lld",&n,&l);
13     l++;
14     for(int i=1;i<=n;i++){
15         ll t; scanf("%lld",&t);
16         sum[i]=sum[i-1]+t;
17         A[i]=sum[i]+i;
18     }
19     front=0,tail=1;
20     for(int i=1;i<=n;i++){
21         while(front+1<tail&&up(q[front+1],q[front])<=A[i]*dn(q[front+1],q[front])) front++;
22         int j=q[front]; dp[i]=dp[j]+pow_(A[i]-A[j]-l);
23         while(front+1<tail&&up(i,q[tail-1])*dn(q[tail-1],q[tail-2])<=up(q[tail-1],q[tail-2])*dn(i,q[tail-1])) tail--;
24         q[tail++]=i;
25     }
26     printf("%lld\\n",dp[n]);
27     return 0;
28 }
View Code

 

1010: [HNOI2008]玩具装箱toy

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 8864  Solved: 3529
[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

HINT

Source

以上是关于BZOJ_1010_[HNOI2008]_玩具装箱toy_(斜率优化动态规划+单调队列)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1010 [HNOI2008]玩具装箱toy

BZOJ1010:[HNOI2008] 玩具装箱toy(斜率优化)

BZOJ1010: [HNOI2008]玩具装箱toy

[HNOI2008]玩具装箱

bzoj1010HNOI2008玩具装箱 toy

BZOJ 1010 HNOI2008 玩具装箱