bzoj1010-[HNOI2008]玩具装箱toy

本文深入探讨了斜率优化在动态规划中的应用,通过具体算法实例解析如何利用斜率优化来提升DP算法效率,特别关注在下凸壳维护中双端队列的应用。

斜率优化.

发现
\[ dp[i] = min(dp[j]+(i−j−1+sum[i]−sum[j]−L)^2 (j<i)\]

\[ dp[i] = min( -2*(sum[i]+i-l-1)*(sum[j]+j)+dp[j]+(sum[j]+j)^2 ) +(sum[i]+i-l-1)^2 \]

其中 \(2*(sum[i]+i-l-1)\), \((sum[j]+j)\) 都是单调的,因此可以斜率优化.

双端队列维护下凸壳.

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
using namespace std;
#define rep(i,l,r) for(register int i=(l);i<=(r);++i)
#define repdo(i,l,r) for(register int i=(l);i>=(r);--i)
#define il inline
typedef double db;
typedef long long ll;

//---------------------------------------
const int nsz=5e4+5;
ll n,l,sum[nsz],dp[nsz];
int qu[nsz],qh=1,qt=0;

il ll p2(ll v){return v*v;}
ll x(int p){return sum[p]+p;}
ll y(int p){return dp[p]+p2(sum[p]+p);}
ll k(int p){return 2*(sum[p]+p-l-1);}
db slope(int p1,int p2){return ((db)y(p2)-y(p1))/((db)x(p2)-x(p1));}

ll sol(){
    dp[0]=0;
    qu[++qt]=0;
    ll k0;
    rep(i,1,n){
        k0=k(i);
        while(qh<qt&&slope(qu[qh],qu[qh+1])<k0)++qh;
        dp[i]=-k0*x(qu[qh])+y(qu[qh])+p2(sum[i]+i-l-1);
        while(qh<qt&&slope(qu[qt-1],qu[qt])>slope(qu[qt],i))--qt;
        qu[++qt]=i;
    }
//  rep(i,1,n)cout<<dp[i]<<' ';
//  cout<<'\n';
    return dp[n];
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0);
    cin>>n>>l;
    rep(i,1,n){
        cin>>sum[i],sum[i]+=sum[i-1];
    }
    cout<<sol()<<'\n';
    return 0;
}

转载于:https://www.cnblogs.com/ubospica/p/9884386.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值