• hihocoder1055 刷油漆(树形DP)


    问题描述:

    有一棵树,树上节点编号1~n,其中节点1为根节点,树上的每个节点有其对应的一个价值。现在要减掉一些枝桠,只留下m个节点的一棵树(必须包含根节点),为这m个节点着色,约束条件是要使剩下m个节点的价值之和最大化。

    算法思路:

    状态定义:dp[x][j]表示以节点x为根的子树中,着色节点数目为j时,从这棵子树中所能获得的最大价值。那么dp[1][m]即为所求。

    状态转移:设节点y为节点x的子节点,那么dp[x][j] = max(dp[x][j], dp[y][k]+dp[x][j-k]),其中1<=k<j。

    整体思路类似于完全背包。

    我的代码:

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <vector>
     4 #include <cstring>
     5 
     6 using namespace std;
     7 
     8 #define MAXN 105
     9 
    10 int dp[MAXN][MAXN], n, m, v[MAXN];
    11 bool vis[MAXN];
    12 struct Tree
    13 {
    14     vector<int> t[MAXN];
    15     void init(int n)
    16     {
    17         for(int i=1; i<=n; ++i) t[i].clear();
    18         memset(&vis[1], 0, n);
    19     }
    20     void addEdge(int a, int b)
    21     {
    22         t[a].push_back(b);
    23         t[b].push_back(a);
    24     }
    25     void solute(int x)
    26     {
    27         vis[x] = true;
    28         memset(dp[x], 0, (m+1)*sizeof(int));
    29         dp[x][1] = v[x];
    30         for(int i=0; i<t[x].size(); ++i)
    31         {
    32             int y = t[x][i];
    33             if(!vis[y])
    34             {
    35                 solute(y);
    36                 for(int j=m; j>=2; --j) //注意这里的遍历顺序
    37                 for(int k=1; k<j; ++k) dp[x][j] = max(dp[x][j], dp[x][j-k]+dp[y][k]);
    38             }
    39         }
    40     }
    41 }tree;
    42 
    43 int main()
    44 {
    45     while(cin>>n>>m)
    46     {
    47         for(int i=1; i<=n; ++i) cin>>v[i];
    48         tree.init(n);
    49         for(int i=0; i<n-1; ++i)
    50         {
    51             int a, b;
    52             cin>>a>>b;
    53             tree.addEdge(a, b);
    54         }
    55         tree.solute(1);
    56         cout<<dp[1][m]<<endl;
    57     }
    58 
    59     return 0;
    60 }

    题目来源:http://hihocoder.com/problemset/problem/1055

  • 相关阅读:
    驰骋工作流引擎-系统变量的引用
    驰骋工作流引擎-表单样本展示
    驰骋工作流引擎CCFLOW下载代码
    初识CSS
    初识HTML标签
    初识JDBC
    通过锁对象解决哲学家就餐问题
    MySQL基本用法
    LRU算法实现,HashMap与LinkedHashMap源码的部分总结
    Java简易实现记事本的打开与保存
  • 原文地址:https://www.cnblogs.com/pczhou/p/4296564.html
Copyright © 2020-2023  润新知