• 树形dp总结:从入门到放弃


    一、如何拥有一棵树 how to build a tree

    存树的方法有很多种,我个人常用的有:

    链式前向星存图法

    因为树也是一种图,所以说对于存图法是适用的。缺点就是不好利用树的性质。

    因为比较普遍,教程也很多,就不再赘述了。

    左儿子右兄弟法

     1 struct node //结构体存树
     2 {
     3     int lson,rson;//因为转变为二叉树,所以只有两个儿子
     4 }a[N];//这个好像叫tree更标准
     5 
     6 void findplace(int x,int y)//x是根,y是要插入的儿子
     7 {
     8     int pos=a[x].lson;//这是在x已经有第一个儿子的情况
     9     while(a[pos].rson!=-1)//循环找直到右儿子(兄弟位)空出
    10         pos=a[pos].rson;
    11     a[pos].rson=y;//成功存入
    12 }
    13 
    14 int main()
    15 {
    16     for(int i=0;i<n;i++)//初始化
    17     {
    18         a[i].lson=a[i].rson=-1;
    19     }
    20     for(int i=1;i<=n;i++)
    21     {
    22         cin>>x>>y>>w;
    23         a[y].val=w;
    24         if(a[x].lson==-1)//x还没有儿子就可以充任
    25             y=a[x].lson;
    26         else
    27             findplace(x,y);//否则就适用上面的函数了
    28     }
    29 }

    优点是可以非常方便地遍历整个树,缺点是有点慢。但是在操作系统内部,文件夹之间似乎也是这么存放的呢。

    遍历的方法:

    void printree(int pos)
    {
        cout<<pos<<endl;
        int r=a[pos].rson,l=a[pos].lson;
        while(r!=-1)//先打印兄弟
        {
            printree(r);
            r=a[r].rson;
        }
        if(l!=-1)//再考虑儿子
            printree(l);
    }

    二、如何状态转移 how to dp

    树上的dp一般状态转移都是和子树相关的,而且第一维一般而言都是当前节点的标号。利用记忆化搜索其实能更好利用树,刷表填表我都不太适应……

    普通dp比较常用的考虑方法是f[i][0/1]表示点i选/不选的情况下,其子树的最优情况

    如果是树形背包,那么f[i][j]表示在以点i为根节点的子树中,选择j个点的最优情况

    当然这个要视具体情况分析而定。

    需要注意的是树形背包的转移方程通常是各个子树的份额分配问题,然后取max或者相加或者玄学操作。当这棵树是二叉树时可以简单地使用单重循环,其他需要多重循环。这时候循环的边界就变得重要了。通常可以考虑记录size(子树节点个数)、直接儿子个数什么的或者其他的题目条件来优化边界。

    一般而言要考虑的问题:叶子节点(也就是边界)、选择和不选择时对应的子节点情况(有什么要求)、根节点怎么处理等。如果没有根节点,可以考虑构建一个虚根;如果题目中是边权,可以考虑下沉至点权来做。注意根节点是不是占用名额!这个是比较重要的。

    三、如何水经验 how to get exp

    luogu上P201x的题目很多都是树形dp的。个人的成长路线是:

    1.没有上司的舞会(经典dp)

    2.二叉苹果树(树形背包入门)

    3.选课(树上依赖背包入门)

    4.战略游戏(普通dp)

    5.“访问”美术馆(有意思)

    5.有线电视网(更有意思)

    本蒟蒻比较菜,所以底线就到这里啦。

  • 相关阅读:
    用Maven插件生成Mybatis代码
    年薪50万的大数据分析师养成记
    利用 index、explain和profile优化mysql数据库查询小结
    perl MQSeries::Queue sync方法
    新零售不简单,当初马云自己都没解释清楚!
    新零售不简单,当初马云自己都没解释清楚!
    elasticsearch 默认不支持检索hadoop
    以不能久驻世上的心态处理日常事务——北漂18年(89)
    数据化管理在餐饮业中的应用
    解决Linux出现"Device eth0 does not seem to be present"问题
  • 原文地址:https://www.cnblogs.com/YuWenzhou-Sakana/p/11765203.html
Copyright © 2020-2023  润新知