[2018.12.9]BZOJ1010 [HNOI2008]玩具装箱toy

本文详细解析了动态规划中的一种优化技巧——斜率优化。通过数学推导,将DP方程转换为线性形式,利用斜率变化实现高效求解。代码示例展示了斜率优化的具体实现过程。

\(sum_i\)\(c_i\)的前缀和。

\(dp_i=min\{dp_j+(i-j-1+sum_i-sum_j-L)^2\}\)

\(f_i=i+sum_i\),\(t=L+1\)

\(dp_i=min\{dp_j+(f_i-f_j-t)^2\}\)

\(\ \ \ \ \ =min\{dp_j+f_i^2+f_j^2+t^2-2f_if_j-2tf_i+2tf_j\}\)

\(\ \ \ \ \ =min\{dp_j+f_j^2-2f_if_j+2tf_j\}+f_i^2-2tf_i+t^2\)

\(\ \ \ \ \ =-max\{-dp_j-f_j^2+2f_jf_i-2tf_j\}+f_i^2-2tf_i+t^2\)

\(k=2f_j\),\(b=-dp_j-f_j^2-2tf_j\)

\(dp_i=-max\{kf_i+b\}+f_i^2-2tf_i+t^2\)

\(f_x\)单调递增。

套斜率优化即可。

斜率优化

code:

#include<bits/stdc++.h>
using namespace std;
int n,c[50010],line[50010],l,r;
long long t,f[50010],dp[50010],k[50010],b[50010];
long long val(int l1,long long x){
    return k[l1]*x+b[l1];
}
bool cov(int l1,int l2,int l3){
    return (b[l2]-b[l1])*(k[l1]-k[l3])>=(b[l3]-b[l1])*(k[l1]-k[l2]);
}
int main(){
    scanf("%d%lld",&n,&t);
    t++;
    for(int i=1;i<=n;i++){
        scanf("%d",&c[i]);
        f[i]=f[i-1]+c[i]+1;
    }
    l=r=1;
    for(int i=1;i<=n;i++){
        while(l<r&&val(line[l],f[i])<=val(line[l+1],f[i]))l++;
        dp[i]=-val(line[l],f[i])+f[i]*f[i]-2*t*f[i]+t*t;
        k[i]=2*f[i];
        b[i]=-dp[i]-f[i]*f[i]-2*t*f[i];
        while(l<r&&cov(i,line[r-1],line[r]))r--;
        line[++r]=i;
    }
    printf("%lld",dp[n]);
    return 0;
}

转载于:https://www.cnblogs.com/xryjr233/p/BZOJ1010.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值