您的位置:首页 > 其它

BZOJ1096 [ZJOI2007]仓库建设(斜率优化dp)

2015-05-25 01:22 387 查看
【题解】

显然,工厂n一定是要建设仓库的,可以设 f[i]:工厂i建设仓库时前i个工厂的最小花费

则:f[i]=min{ sigma( (xi-xk)*pk ) + f[j] +ci },0<=j<i,k从j+1循环到i

设 s[i]=p[1]+p[2]+…+p[i],t[i]=x[1]*p[1]+x[2]*p[2]+…x[i]*+p[i]

则:f[i]=min{ xi*(si-sj) - (ti-tj) + f[j] +ci }

设 m[i]=f[i]+t[i]

斜率表示为:(m[j]-m[k])/(s[j]-s[k])

维护下凸壳,优化之即可

【代码】

#include<stdio.h>
#include<stdlib.h>
typedef long long LL;
LL x[1000005],c[1000005],s[1000005],t[1000005],m[1000005],f[1000005];
int q[1000005];
double K(int j,int k)
{
    return (double)(m[j]-m[k])/(double)(s[j]-s[k]);
}
int main()
{
    LL p;
    int n,i,head=0,tail=1;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%lld%lld%lld",&x[i],&p,&c[i]);
        s[i]=s[i-1]+p;
        t[i]=t[i-1]+x[i]*p;
    }
    for(i=1;i<=n;i++)
    {
        while(tail-head>=2&&K(q[head],q[head+1])<(double)x[i]) head++;
        f[i]=x[i]*(s[i]-s[q[head]])-(t[i]-t[q[head]])+f[q[head]]+c[i];
        m[i]=f[i]+t[i];
        while( tail-head >= 2 && K(q[tail-2],q[tail-1]) > (double)(m[q[tail-1]]-m[i])/(double)(s[q[tail-1]]-s[i]) ) tail--;
        q[tail++]=i;
    }
    printf("%lld",f
);
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: