zoukankan      html  css  js  c++  java
  • 树形DP&最简单的树形DP例题

    一、概念  

      顾名思义,树型动态规划就是在“树”的数据结构上的动态规划,平时作的动态规划都是线性的或者是建立在图上的,线性的动态规划有二种方向既向前和向后,相应的线性的动态规划有二种方法既顺推与逆推,而树型动态规划是建立在树上的,所以也相应的有二个方向: 

        1、叶->根:在回溯的时候从叶子节点往上更新信息

        2、根 - >叶:往往是在从叶往根dfs一遍之后(相当于预处理),再重新往下获取最后的答案。

        不管是 从叶->根 还是 从 根 - >叶,两者都是根据需要采用,没有好坏高低之分。

    二、优点

      树本身至少就有“子结构”性质(树和子树);也本身就具有递归性。所以在树上DP其实是其所当然的事,相比线性动态规划来讲,转移方程更直观,更易理解。

    三、难点

      1、和线性动态规划相比,树形DP往往是要利用递归的,所以对递归不熟悉的同学,是一道小小的障碍,说是小小的,因为要去理解也不难。

       2、细节多,较为复杂的树形DP,从子树,从父亲,从兄弟……已经一些小的要处理的地方,脑子不清晰的时候做起来颇为恶心
       3、状态表示和转移方程,也是真正难的地方。做到后面,树形DP的老套路都也就那么多,难的还是怎么能想出转移方程,状压DP、概率DP这些特别的DP应该说做到最后都是这样!
     
    前置知识:边表
    //一、边表(链式前向星) 
    struct edge
    {
        int e;//e为一条边的终点 
        int next;//next为同一父节点的下一条边
                //例如,3和2是1的子节点且3在2前面
                //那么3.next=2 
    }ed[maxn];
    
    int first[maxn];
    //first[n]是父节点为n的第一条边 
    
    //加边: 
    void add_edge(int s,int e)//添加一条从s到e的边 
    {
        en++;//新加入的边 
        ed[en].next=first[s];
        //表示:现在新加的这一条边,当做从s开始的第一条边
        //类似一个倒序输入,越晚加的边序号越小 
        first[s]=en;
        //由上述分析可知:那么父节点为s的第一条边就是en了 
        ed[en].e=e;    
        //这一条边的终点就是e 
    } 
    
    //遍历:
    for(int p=first[s];p!=0;p=ed[p].next)
    //p从s的第一条子边开始循环,每次变成相同父节点(s)的下一条边 
    //直到为0时结束循环 

    最简单的树形DP:给定一棵N个点的树,用树形DP的方法求出该棵树的节点数目

    设置状态:f[i]为以i为根的子树,此时表示以i为根的子树有多少节点 
    void dfs(int now,int fa)
    {
        //fa为now的父节点 
        f[now]=1;
        for(int p=first[now];p!=0;p=ed[p].next)
            if(ed[p].next!=fa)
            {
                //如果这条边不是指向它父亲的话 
                dfs(ed[p].e,now);
                //就dfs,把now当作父节点 
                f[now]+=f[ed[p].e];
                //此时ed[p].e是now的一个子节点 
            }
    }
  • 相关阅读:
    关于Hyper-V备份的四大注意事项
    未找到导入的项目,请确认 <Import> 声明中的路径正确
    IDC门外汉-单线、双线、智能多线、BGP的区别
    国内主流云主机比较
    Error : The specified component was not reported by the VSS writer (Error 517) in Windows Server 2012 Backup
    [MSDN] Windows Server 2012 R2 简/繁/英下载
    深入浅出VC++串口编程之基于Win32 API
    Remon Spekreijse CSerialPort串口类的修正版2014-01-10
    Remon Spekreijse CSerialPort用法
    “CObject::operator =”: 无法访问 private 成员(在“CObject”类中声明)
  • 原文地址:https://www.cnblogs.com/liumengliang/p/12756262.html
Copyright © 2011-2022 走看看