您的位置:首页 > 编程语言 > PHP开发

【斜率优化DP】玩具装箱

2012-03-24 19:21 148 查看
[HNOI2008]玩具装箱toy
Time Limit:1000MS Memory Limit:165536K

Total Submit:5 Accepted:5
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


斜率优化,方程很简单,优化也很简单,懒得写了。

对于这种题要注意两个地方就好了。

1、双端队列的区间是什么区间。比如说这里是左闭右闭。首先入队第一个元素,r应该还是0。等等等。

2、方程系数分离之后如果要作除法,要注意不等号需不需要变号

#include <cstdio>
#include <iostream>
const char fi[] = "toy.in";
const char fo[] = "toy.out";

const long maxn = 50010;
typedef long long ll;
long C[maxn];
ll sumpi[maxn];
ll sum[maxn];
long que[maxn];
ll L;
long n;
long l = 0;
long r = 0;
ll f[maxn];

inline ll Calc(long j,long k)
{
return f[j]+sumpi[j]*sumpi[j]-f[k]-sumpi[k]*sumpi[k];
}

inline int getint()
{
int res = 0; char tmp;
while (!(isdigit(tmp = getchar())));
do res = (res << 3) + (res << 1) + tmp - '0';
while ((isdigit(tmp = getchar())));
return res;
}

int main()
{
freopen(fi, "r", stdin);
freopen(fo, "w", stdout);
n = getint();
L = getint();
for (long i=1;i<n+1;i++)
{
C[i] = getint();
sum[i] = sum[i-1] + C[i];
sumpi[i] = sum[i] + i;
}
r = -1;
que[++r] = 0;
for (long i=1;i<n+1;i++)
{
ll lambda = sumpi[i]-L-1;
while (l<r&&Calc(que[l],que[l+1])>2*lambda*(sumpi[que[l]]-sumpi[que[l+1]])) l++;
f[i] = f[que[l]] + (-1+sumpi[i]-sumpi[que[l]]-L)*(-1+sumpi[i]-sumpi[que[l]]-L);
while (l<r&&Calc(que[r-1],que[r])*(sumpi[que[r]]-sumpi[i]) >
Calc(que[r],i)*(sumpi[que[r-1]]-sumpi[que[r]])) r--;
que[++r] = i;
}
printf("%lld",f
);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  优化 lambda output input c