zoukankan      html  css  js  c++  java
  • [算法模版]斜率优化

    [算法模版]斜率优化

    在之前的博客中,有几道斜率优化的例题。但是那些例题都是把“状态”看作“线段”来处理的。最后我发现,还是把状态当成二维平面上的点比较好处理。

    这里以昨天模拟赛的一道题作为例题来说一说斜率优化。

    ZROI-#885-猫

    本文内容大部分由Harry_bh撰写,特此鸣谢。


    (Dp_{i,j}=Dp_{i-1,k})

    (dp_i=dp'_j+val(i-j)-(s_i-s_j))

    假设 (j) 是最优决策点

    假设 (j<k)

    对于任意的 (k) 都满足

    [dp_j+val(i-j)-(s_i-s_j)leq dp_k+val(i-k)-(s_i-s_k)\ dp_j-dp_k+s_j-s_kleq val(j-k)\ cfrac{dp_j-dp_k+s_j-s_k}{j-k}geq val\ ]

    这个东西他的意义就是 两个点 ((j,dp_j+s_j)),((k,dp_k+s_k)) 所形成的直线的斜率

    所以如果 (j)(k) 更优,那么这个斜率就满足。。。。

    你维护一个队列,那么我们要使得队首元素就是我们想要的最优决策点,因为队首元素成立的条件是(第一个点和第二个点的斜率geq val)。而(val)是单调递增的,所以我门需要让队列中每个点和上一个点的斜率是单调递增的(即下凸壳)。

    我们在向队尾插入新的元素时,需要判断,如果(tail,tail-1)的斜率大于(插入元素,tail-1)的斜率时,就需要把(tail)删掉。(具体的意思就是(tail)的状态并没有优于插入元素,而在这个队列中的性质是每个队中状态要优于他后面的所有状态)

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #define ll long long
    #define maxn (int)(1e5+100)
    ll dp[1005][50020],dis[maxn],tim[50020],n,m,p,pre[maxn],h[maxn],t[maxn],queue[maxn];
    using namespace std;
    int main() {
        scanf("%lld%lld%lld",&n,&m,&p);
        for(int i=2;i<=n;i++){scanf("%lld",&dis[i]);dis[i]+=dis[i-1];}
        for(int i=1;i<=m;i++){scanf("%lld%lld",&h[i],&t[i]);tim[i]=t[i]-dis[h[i]];}
        sort(tim+1,tim+1+m);for(int i=1;i<=m;i++)pre[i]=tim[i]+pre[i-1];
        memset(dp,0x3f,sizeof(dp));dp[0][0]=0;
        for(int i=1;i<=p;i++) {
            ll head=1,tail=0;
            for(int j=0;j<=m;j++) {
                while(head<tail&&(dp[i-1][queue[head]]+pre[queue[head]]-dp[i-1][queue[head+1]]-pre[queue[head+1]])>tim[j]*(queue[head]-queue[head+1]))head++;
                dp[i][j]=dp[i-1][queue[head]]+tim[j]*(j-queue[head])-(pre[j]-pre[queue[head]]);
                while(head<tail&&(dp[i-1][queue[tail-1]]+pre[queue[tail-1]]-dp[i-1][queue[tail]]-pre[queue[tail]])*(queue[tail-1]-j)>(dp[i-1][queue[tail-1]]+pre[queue[tail-1]]-dp[i-1][j]-pre[j])*(queue[tail-1]-queue[tail]))tail--;
                queue[++tail]=j;
            }
        }
        printf("%lld",dp[p][m]);
    }
    
  • 相关阅读:
    IE8及其以下浏览器边框圆角兼容问题
    关于git的一些指令及遇到的问题和解决方法
    vue项目环境搭建及运行
    webpack中的重要功能
    webpack 的重要功能
    c++ stl sort 自定义排序函数cmp要遵循 strict weak ordering
    spring boot 包jar运行
    windows上传文件到linux云服务器上
    最少硬币数目的问题
    leetcode 415 两个字符串相加
  • 原文地址:https://www.cnblogs.com/GavinZheng/p/11318982.html
Copyright © 2011-2022 走看看