zoukankan      html  css  js  c++  java
  • DP从入门到入土

    DAGDP

    食物链
    简单的拓扑DP,转移方程通式 (f[v]+=f[u],rd[v]--)
    犯错

    for (int i=head[u];i;i=e[i].nxt)
            {
                int v=e[i].v;
                f[v]+=f[u];
                rd[v]--;
                if (!rd[v]) q.push(v);
            }
    /*6,v写成i*/
    for (int i=1;i<=n;i++)
            if (!rd[i]) 
            {
                if (cd[i]) f[i]=1;
                q.push(i);
            }
    /*特殊情况的处理,入队的对象*/
    

    Code

    区间DP

    P3205 [HNOI2010]合唱队
    这是一种区间DP的典型模板,左右操作,求方案数
    对于这类问题,可以分别表示左右两种操作
    (f[i][j]) 表示在区间 ([i,j],i) 从左边插入
    (g[i][j]) 表示在区间 ([i,j],j) 从右边插入
    两个dp数组自然拥有独特的两个阶段

    • 对于 (f): 相对于上一区间,要么是从 (i+1) 比较,再加入,或者上一次加进去的是 (j) ,则阶段为(f[i+1][j],g[i+1][j]),
      注意这是上一阶段,换句话说就是该阶段的 (i)是被加入的,也就是上一阶段是不存在 (g[i][j])这中转移状态
    • 对于 (g): 同理可耻,要么是上一次加入的是 (i),也就是加到左边,即 (f[i][j-1]),要么就是上一次加进去的是 (j-1) ,即 (g[i][j-1]);
      注意上一阶段,不存在 (j) 的情况
      错误 转移方程式抄错
    for (int len=2;len<=n;len++)
            for (int i=1;i+len-1<=n;i++)
            {
                int j=i+len-1;
                f[i][j]=(f[i+1][j]*(a[i+1]>a[i])+g[i+1][j]*(a[i]<a[j]))%mod;
                g[i][j]=(f[i][j-1]*(a[j]>a[i])+g[i][j-1]*(a[j]>a[j-1]))%mod;
            }
    /*6,抄错,炒成:g[i][j]=(g[i][j-1]*(a[j]>a[i])+g[i][j-1]*(a[j]>a[j-1])%mod/
    

    总结 此类区间DP,转移的方向明确,要么上一阶段的左边要么右边,不需要区间枚举
    Code

    序列DP

    粉刷匠
    序列DP
    对于每一行 (f[i][j]=max(f[k][j-1]+max(蓝 红,[k,i]))
    对于每一行 (dp[i][j])(i)表示行号,
    (dp[i][j]=max(dp[i][j-k]+f[m][k]);)
    答案 (dp[n][T]);
    注意 处理前缀和优化时出现了错误

    for (int k=0;k<l;k++)
                    {
    //                    int s1=a[i][l]-a[i][k];
    //                    int s2=b[i][l]-b[i][k];
                        int js=sum[i][l]-sum[i][k];
                        f[l][r]=max(f[l][r],f[k][r-1]+max(js,l-js-k));
                    }
    

    Code

    树形DP

    小齐挖矿
    对于一个子节点,距离最近的要么就是父亲,要么就是父亲去的仓库

    Code

    女仆咖啡厅桌游吧
    tmd 燃起来了! 有点饲喂量的树形DP

    Code

    P7103 「C.E.L.U-01」族谱树

    • 暴力做法 求每个点的 (LCA)直接询问,不过会超时

    • 树形DP
      首先 (LCA)的一种性质,如果以 (i) 为节点的子树具有相同的最近公公祖先 (i),换句话说,若果这个点是某两个点的LCA,那么他的父亲必然是公公祖先

    就这一性质,我们假设 (u) 即节点是第 (k) 层节点的最近公共祖先,那么就看看他的儿子 (v)是不是 (k+1)的了,

    但是要 (v)成为深度 (k+1) 的LCA,必须满足子树 (v) 的最大深度超过 (k+1),故我们需要预处理出每个节点的最大深度

    还有一种情况,如果 (u) 的儿子有多个,假若存在两个以上的 (v_1,v_2..) 满足 (f(v)>=k+1) ((f[v])表示该点的最大深度),那么他们都不可以成为LCA

    Code

    P5658 [CSP-S2019] 括号树

    P4438 [HNOI/AHOI2018]道路
    记忆化搜索,树形思想,公式迷惑
    P2899 [USACO08JAN]Cell Phone Network G
    水题
    P2458 [SDOI2006]保安站岗
    水题

    换根DP

    P3478 [POI2008]STA-Station
    换根式子:(f[v]=-size[v]+f[u]+(n-size[v]))
    用人话讲就是:根有 (u)(v)时,子树 (u) 全体深度+1(不含子树(v)),子树 (v)全体深度-1

    P2986 [USACO10MAR]Great Cow Gathering G

    换根水题
    (ans)记得开大点,否则60
    转移式子:(dp[v]=dp[u]-size[v] imes e[i].w+(sum-size[v]) imes e[i].w)

    背包DP

    P3188 [HNOI2007]梦幻岛宝珠

    关于二进制神奇做法的背包,感觉是在每一位二进制上进行背包

    两个转移点

    • 同级转移,我们有
      (f[i][j]=max{f[i][j-a[i]]+val[i]})
    • 高位转低位我们有
      (f[i][j]=max{f[i][j-k]+f[i-1][min(1000,(k<<1)|((w&(1<<(b-1)))!=0)]})

    位运算

    P3423 [POI2005]BAN-Bank Notes

    二进制拆分,注意数组越界(拆分写挂,变成负数)

    Code

    [P1782](https://www.luogu.com.cn/problem/P1782)

    典型的旅行商问题,多重背包里套完全背包,我用的是二进制拆分(真好用虽然60,这里建议直接吸氧!

    Code

    期望DP

    P1654 OSU!

    Code

    装压DP

    讲真的,装压是我见过最优美的DP题目

    P1433 吃奶酪

    (f[i][s]) 表示起点为 (i),完成状态为 (s) 的最小距离

    转移有 (f[i][s]=min{f[j][s-(1<<(i-1)]+dis(i,j)})

    优美之处在于:距离不是限制矩阵的大小,只是运算的工具,通过位运算进行判重 if(!(s&(1<<(i-1)),转移也非常优美,更新新的起点,并在二进制状态下更新,beautiftying

    [USACO12MAR]Cows in a Skyscraper G

    这题让初次学习的我知道了初始化,通过判断该点是否在状态之中,可谓妙哉!if((j)&(1<<k))

    (f[i][j]) 表示有i个层时,满状态下的最小体积书
    最后用过倒叙判断是否为inf即可

    P3226 [HNOI2012]集合选数
    一道构造好题!

    单调队列优化

    P1823 [COI2007] Patrik 音乐会的等待

  • 相关阅读:
    如何只用5分钟完成数据 列表、创建页面
    从零开始搭建一个PaaS平台
    C# 多线程猜想
    使用Golang + lua实现一个值班机器人
    如何使用Golang实现一个API网关
    记一次Windb死锁排查
    怎样在PaaS平台上搭建一个会自动关闭的会议室
    JS Object To C# ASP.Net ModelBind
    重写了一遍授权思路
    授权详细设计
  • 原文地址:https://www.cnblogs.com/lToZvTe/p/14527396.html
Copyright © 2011-2022 走看看