zoukankan      html  css  js  c++  java
  • 单调性优化dp

    单调性优化dp主要有2种:

    1.dp本身的单调性。dp有多种取值,取某一部分有一个分界线。

    使用这个性质可以快速计算dp值

    这种dp的性质一般只能靠猜。也能通过思考,打表得来。

    例题有:

    IOI2018 会议

    CF573E

    NOIP2019 划分

    2.决策单调性。

    决策单调性通常用于1d-1d dp。它的转移方程通常是:$f[i]=min(f[j]+w(i+1,j))$或$f[i]=max(f[j]+w(i+1,j))$

    对于$a<b<c<d$,当b转移到c比a转移到c优,则b转移到d比a转移到d优

    从这个可以推出一个结论:不可能出现i<j,且i的决策点位置>j的决策点,实际上就是决策点是有序的

    实际上就是如下2个公式:

    $f[b]+w(b+1,c)<f[a]+w(a+1,c)$

    $f[b]+w(b+1,d)<f[a]+w(a+1,d)$

    联立得到

    $w(b+1,c)-w(b+1,d)<w(a+1,c)-w(a+1,d)$

    $w(b+1,c)+w(a+1,d)<w(a+1,c)+w(b+1,d)$

    实际上会发现,当$mathrm{w} (i, j + 1) + mathrm{w} (i + 1, j)leqmathrm{w} (i, j) + mathrm{w} (i + 1, j + 1)$时上面的公式是成立的。

    如果设$f(i)=w(i,j)-w(i,j+1)$,则上面的式子变成了$f(i)>=f(i+1)$,就是当i<j时,$f(i)>=f(j)$

    所以可以得到$f(b+1)<=f(a+1)$,$w(b+1,j)-w(b+1,j+1)<=w(a+1,j)-w(a+1,j+1)$

    $w(b+1,j)-w(a+1,j)<=w(b+1,j+1)-w(a+1,j+1)$

    如果设$g(j)=w(b+1,j)-w(a+1,j)$,容易得到$g(i)<=g(i+1)$,就是当i<j时,$g(i)<=g(j)$

    则$g(c)<=g(d)$,$w(b+1,c)-w(a+1,c)<=w(b+1,d)-w(a+1,d)$

    $w(b+1,c)+w(a+1,d)<=w(a+1,c)+w(b+1,d)$

    证明了上面的命题。

    决策单调性大多数只能靠猜,打表得到。

    维护有2种方法:分治法,二分队列法。

    分治法的核心代码是:(从f转移到g)

    void fz(int l,int r,int x,int y){
        if(l>r||x>y)return;
        int o,md=(l+r)/2;
        for(int i=x;i<=min(md,y);i++)
            if(f[i]+val(i+1,md)<g[md]){
                g[md]=f[i]+qu(i+1,md);
                o=i;
            }
        fz(l,md-1,x,o);
        fz(md+1,r,o,y);
    }

    它的意义是:

    现在的决策点被锁定在区间[x,y],现在要确定md的决策点,则扫一遍[x,y]

    则由于决策点的有序性,[l,md-1]的决策点被锁定在[x,o]内,[md+1,r]被锁定在[o,r]内,继续分治下去可以得到f数组,一次时间复杂度nlogn

    优点:代价函数的移动次数是nlogn的。这样在一些题目内可以保证复杂度,且代码容易写。

    缺点:必须保证更新g的数组f没有依赖。

    二分队列法的核心代码是:

    q[1]=(no){1,n,0};
    for(int i=1;i<=n;i++){
        f[i]=cl(i,q[h].s);
        la[i]=q[h].s;
        if(q[h].l==q[h].r)h++;
        else q[h].l++;
        while(h<=t&&cl(q[t].l,q[t].s)>cl(q[t].l,i))t--;
        if(h>t)q[++t]=(no){i+1,n,i};
        else{
            int l=q[t].l+1,r=q[t].r+1;
            while(l<r){
                int md=(l+r)/2;
                if(cl(md,q[t].s)>cl(md,i))r=md;
                else l=md+1;
            }
            q[t].r=l-1;
            if(l<=n)q[++t]=(no){l,n,i};
        }
    }

    其中队列的结构体是存储连续的相同的决策点。

    每次插入一个点并且更新队列,在队列中二分出被更新的决策点。

    优点:dp数组之间可以有依赖

    缺点:必须保证一次计算代价函数的时间复杂度较小,否则复杂度会退化。且代码比分治法更难写。

    例题:

    uoj285(没做)

    诗人小G

    CF868F

    除此之外,带四边形不等式的dp也可以带权二分,详见https://www.cnblogs.com/Itst/p/12805678.html

  • 相关阅读:
    oracle 自动备份
    oracle 常用操作语句
    数据库创建及使用注意事项
    oracle 导入 导出 备份
    http://blog.sina.com.cn/s/blog_5fc8b3810100iw9n.html
    利用普通工具编译的第一个Servlet
    对java:comp/env的研究(转)
    MyEclipse配置tomcat、jdk和发布第一个web项目
    构建 SSH 框架(转)
    Java Project和Web Project
  • 原文地址:https://www.cnblogs.com/cszmc2004/p/12682265.html
Copyright © 2011-2022 走看看