hdu 4258(斜率优化DP)

来源:互联网 发布:tp的访客网络占带宽吗 编辑:程序博客网 时间:2024/05/18 20:11

题目大意:将n个升序数字序列,分成几组连续的序列 ,每一组的所得值,等于最右边的num2减去最左边 的num1,的平方+c即(numi-numj)^2+c

解题报告 人:GHQ(SpringWater)

分析可得:(dp[j2]-dp[j1]+num[j2+1]*num[j2+1]-num[j1+1]*num[j1+1])/(2(num[j2+1]-num[j1+1]))《=num[i]时,j2比j1更优,可知这是一个凹曲线斜率优化;

i<j<k时且k(i,j)>=k(j,k)时,那么j是可以去掉的。

1.当 k(j,k)《=num[i]时,j没 k优,可去 j

2.当 k(j,k)>=num[i]时,则k(i,j)》=num[i],i比j优秀,可去j!


自己默思:1,:为什么当前队列左边相邻的k(l,l+1) 第一个满足>num[i]时,即l比l+1优,则l比右边的所有 都优,因为l和右边的组合斜率是增加的,l+1同样优于l+2,

由传递性可得,第一次l为最优,

2:为什么当前i总用和相邻的(r-1,r)和(r,i)比较即可确定是否删除r,因为当k(r,i)>=k(r,r-1)则k(r,i)大于在队列里所有任意 组合 的 斜率!能确保 k(r,i)是最大的 斜率。

也就 保证了,斜率递增!

当>=num[i]时为凸曲线斜率优化!

hdu4258#include<stdio.h>#define MAXN 1000005int que[10000];__int64 num[MAXN],dp[MAXN];double k(int j1,int j2){return (double)(dp[j2]-dp[j1]+num[j2+1]*num[j2+1]-num[j1+1]*num[j1+1])/(double)(2.0*(num[j2+1]-num[j1+1]));}int main(){int n, i, l, r;__int64 c;while(scanf("%d%I64d",&n,&c) && (n || c)){for(i = 1; i <= n; i++)scanf("%I64d",&num[i]);dp[0] = 0;dp[1]=c;que[l = 0] = 0;que[r = 1] = 1;for(i = 2; i <= n; i++){while((l < r)&&k(que[l],que[l+1])<=(double)num[i])++l;dp[i]=dp[que[l]]+c+(num[i]-num[que[l]+1])*(num[i]-num[que[l]+1]);while((l < r)&&k(que[r],i)<=k(que[r-1],que[r]))--r;que[++r] = i;}printf("%I64d\n",dp[n]);}return 0;}


原创粉丝点击