[BZOJ3675][Apio2014]序列分割(斜率优化dp)

本文介绍了一种结合动态规划与凸包优化技术求解特定类型最优化问题的方法。通过实例详细展示了如何利用凸包来维护一系列直线,并通过比较不同直线间的相对位置以达到去除冗余直线的目的,从而优化动态规划的效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:
我是超链接
题解:
f[i][j]=max{f[k][j-1]+(s[n]-s[k])*(s[k]-s[j1])}
每次运行的时候k是已知的
代码:

#include <cstdio>
#include <iostream>
#define LL long long
#define N 100005
using namespace std;
LL f[N],s[N],g[N];int q[N],n;
LL K(int j){return s[j];}
LL B(int j){return -(LL)s[n]*s[j]+g[j];}
LL Y(int i,int j){return (LL)s[i]*K(j)+(LL)B(j);}
bool cover(int x1,int x2,int x3)
{
    LL w1=(LL)(K(x1)-K(x2))*(LL)(B(x3)-B(x1));
    LL w2=(LL)(K(x1)-K(x3))*(LL)(B(x2)-B(x1));
    return w1<=w2;  
}
int main()
{
    int k,i,x,j;
    scanf("%d%d",&n,&k);
    for (i=1;i<=n;i++){
        scanf("%d",&x);s[i]=s[i-1]+x;
    }
    LL ans=0;int l,r;
    for (i=1;i<=k;i++)
    {
        l=r=0;
        for (j=1;j<=n;j++)
        {
        while (l<r && Y(j,q[l])<=Y(j,q[l+1])) l++;
        f[j]=(LL)Y(j,q[l])+(LL)(s[n]-s[j])*s[j]; 
        while (l<r && cover(j,q[r-1],q[r])) r--;
        q[++r]=j;
        }  
        for (j=0;j<=n;j++) g[j]=f[j];
    }   
    for (i=1;i<n;i++) ans=max(ans,g[i]);
    printf("%lld",ans);
}

总结:
说一下排除直线的超烦情况吧
y1=k1x+b1 ; y2=k2x+b2 ; y3=k3x+b3
那么现在y1和y3想要把y2挤出去
化简得到的w1=(k1-k2)(b3-b1) ; w2=(k1-k3)(b2-b1)
代表着y1y3的交点的x值对应的y2——y与y2
1、w1**>** w2 ——> y2< y 向上包围取大值
这里写图片描述
2、w1**<** w2 ——> y2> y 向下包围取小值
恩那就不画图了(才不是懒嘞)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值