zoukankan      html  css  js  c++  java
  • 部分树形DP的优化

    ural1018. Binary Apple Tree

    题目大意

    有一棵n个节点的树,树上每个节点有一个值,选择m个节点使这些节点值的和最大
    要求:如果选当前节点,则必须选它的父节点

    解法:

    我们设dp[i][j]为以i为根的树上留j个节点的最大值,转移方法如下

    for(int j=min(q,size[x]);j>1;j--){//size表示子树的大小 
        for(int k=min(j-1,size[v]);k>0;k--){//因为父节点要保留所以j-k要>=1 
            dp[x][j]=max(dp[x][j],dp[v][k]+dp[x][j-k]);//v为x的子节点 
        }
    }

    复杂度O(n*m^2)

    “金明的预算方案”加强版

    题目大意

    有一棵n个节点的树,树上每个节点有一个代价和一个价值,选择若干个节点使这些节点的价值最大并且代价不超过m
    要求:如果选当前节点,则必须选它的父节点$nle 5000,mle 10000$

    题解:

    如果还像上一题那样考虑的话,dp[i][j]为以i为根的子树代价为j的最大价值,
    共有m*n个状态,每个状态O(m)转移,复杂度O(m*m*n),虽然达不到那么高,但也一定会超时

    考虑优化

    首先将所有节点后序遍历,p[i]保存dfs序为i的节点编号,
    l[i]保存在i节点的子树之前遍历的最后一个dfs序,如下图

    节点右侧的为节点的dfs序,左上角的为l的值:
    如p[4]=7,l[7]=3代表7号节点dfs序为4,在7节点的子树之前遍历的最后一个dfs序为3

    然后将dp[i][j]的意义改为前i个遍历的节点代价为j的最大值
    dp[i][j]=max(dp[l[u]][j](当前节点不选,则子树都不能选),dp[i-1][j-v[u]]+w[u](选当前节点))   注:u=p[i];
    于是状态转移变成O(1)了,时间复杂度O(n*m)

    思考一下上一题是否也可以这样优化?

    只需将dp[i][j]的意义改为前i个遍历的节点留j个的最大值即可,其他转移都一样

  • 相关阅读:
    java学习笔记(四)
    Sigmoid 函数
    Neural Architectures for Named Entity Recognition 学习笔记
    java学习笔记(三)
    java学习笔记(二)
    Java学习笔记(一)
    shell 小技巧
    Network Embedding 相关论文
    C++学习笔记(二)
    js判断某字符出现的个数
  • 原文地址:https://www.cnblogs.com/bennettz/p/7883012.html
Copyright © 2011-2022 走看看