zoukankan      html  css  js  c++  java
  • 简单了解树形DP

    今天在B站看了一个树形DP教学视频有所收获,做一个小小的总结

    AV号和链接在这:av12194537

    那么先介绍一下树形DP

    树形DP就是在树这个特殊的数据结构上进行的DP。有两种方向:自顶向下自底向上

    树形DP运用了DFS的方式。

    一般来说都是用自底向上的方向,也就是从叶子节点到根节点。如果采用自顶向下的方式,那么要先进行一遍自顶向下的DFS(预处理),再由根节点到叶子结点获取想要的答案。

    用一个经典入门题讲解一下:没有上司的舞会

    题目大意就是给一棵树每个节点给定一个价值,子节点和父节点不能同时选取,求能够选取的最大价值。

    我们用dp[u][0]表示不选取u节点u子树(包括u在内)能获得的最大价值,dp[u][1]表示选取u节点u子树(包括u在内)能获得的最大价值。

    w[u]表示单个u节点的价值。

    我们从根节点开始进行DFS遍历,遍历完整棵树以后回溯的同时就开始自底向上获取答案。对于任意一个节点u,要得到它的包括自身的子树的价值的最大值,这个最大值需要记录两个,一个是选了自身,一个是没选自身,也就是dp[u][1]和dp[u][0]。如果没有选自身,那么每个子节点都可选可不选,u的最大值就加上每个子节点选和不选的两个最大值中较大的那个,等于Σ(max(dp[vi][0], dp[vi][1]))(vi是u的第i个字节点)。状态转移方程就是 dp[u][0] += max(dp[v][0], dp[v][1]);而如果选了u节点自身,那么它所有的子节点都不能选,最大值就等于Σ(dp[v][0]),转态转移方程就是 dp[u][1] += dp[v][0]

    最后只要比较根节点的两个最大值,大的那个就是想要的结果。

    上代码:

    void Dfs(int u)
    {
        dp[u][0] = 0;
        dp[u][1] = w[u];
        for(int v:e[u]) //用v代表根节点
        {
            Dfs(v);//因为要从叶子节点自底向上,所以先遍历一遍所有节点
            dp[u][0] += max(dp[v][0], dp[v][1]);
            //不选u节点的话子节点v可选可不选
            dp[u][1] += dp[v][0];
            //选u节点的话字节点v只能不选
        }
    }
    
    int main()
    {
        ...
        Dfs(root);//从根节点开始DFS;
        maxvalue = max(dp[root][0], dp[root][1]);
        //最后比较选根节点和不选根节点哪个大
        ...
        return 0;
    }
  • 相关阅读:
    (二)全局属性
    (十二)this关键字
    (十一)构造方法的重载和成员方法的重载
    (十)foreac遍历、break和countinue以及标签和switch循环
    java集合
    关于java赋值操作的原子性问题
    spring list map set
    apache benchmark
    为什么java web项目中要使用spring
    spring IOC
  • 原文地址:https://www.cnblogs.com/Lightfall/p/9347160.html
Copyright © 2011-2022 走看看