zoukankan      html  css  js  c++  java
  • ZOJ 3201 树形背包问题

    题目大意:

    0~n-1号这n个点,每个点有个权值,由无向边形成了一棵树,希望在这棵树上找到一棵长为m的子树使总的权值最小

    基本的树形背包问题

    令dp[u][j] 表示u号节点对应子树中有j个节点所能得到的最大权值

    dp[u][1] = val[u]

    dp[u][j] = max{dp[v][k] + dp[u][j-k]} j>1  1=<k<j

    我们通过dfs自底向上更新

    在dfs过程中建立一个 j ,k 的循环即可

    我一开始想的时候认为这个只做到了 u 的下方考虑,如果所得到的子树是要往u的上方走怎么办,想着自顶向上多一次dfs,然后就再也想不出来了- -

    其实后来想想却发现如果要往上走,那么就得到的是以走到最上方的那个节点所形成的子树,那个值也已经在dp数组中保存了,不用我多去考虑了

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 using namespace std;
     5 
     6 const int N = 105;
     7 int first[N] , k , val[N] , dp[N][N];
     8 
     9 struct Edge{
    10     int y , next;
    11 }e[N<<1];
    12 
    13 void add_edge(int x , int y)
    14 {
    15     e[k].y = y , e[k].next = first[x];
    16     first[x] = k++;
    17 }
    18 
    19 void  dfs(int u , int fa , int m)
    20 {
    21     dp[u][1] = val[u];
    22     for(int i = first[u] ; i!=-1 ; i=e[i].next)
    23     {
    24         int v = e[i].y;
    25         if(v == fa) continue;
    26         dfs(v , u , m);
    27         for(int j = m ; j>=2 ; j--){
    28             for(int k=1 ; k<j ; k++)
    29                 dp[u][j] = max(dp[u][j] , dp[v][k] + dp[u][j-k]);
    30         }
    31     }
    32 }
    33 
    34 int main()
    35 {
    36    // freopen("a.in" , "r" , stdin);
    37     int n , m , x , y;
    38     while(scanf("%d%d" , &n , &m)==2){
    39         for(int i =0 ; i<n ; i++)
    40             scanf("%d" , val+i);
    41 
    42         memset(first , -1 , sizeof(first));
    43         k=0;
    44         for(int i=1 ; i<n ; i++){
    45             scanf("%d%d" , &x , &y);
    46             add_edge(x , y);
    47             add_edge(y , x);
    48         }
    49 
    50         memset(dp , 0 , sizeof(dp));
    51         dfs(0 , -1 , m);
    52 
    53         int maxn = 0;
    54         for(int i=0 ; i<n ; i++){
    55             maxn = max(maxn , dp[i][m]);
    56         }
    57         printf("%d
    " , maxn);
    58     }
    59     return 0;
    60 }
  • 相关阅读:
    @MapperScan 注解和 mybatis.mapper-locations 配置两者缺一不可
    com.mysql.cj.jdbc.Driver和com.mysql.jdbc.Driver的区别
    定时任务框架Quartz-(一)Quartz入门与Demo搭建
    js分页的实现代码
    圣杯布局中对left盒子设置负内边距-100%的一点解释
    前端小知识--为什么你写的height:100%不起作用?
    CSS:实现垂直居中的常用方法
    [jdk源码阅读系列]Java中System.arraycopy()的用法
    [jdk源码阅读系列]overflow-conscious code
    省选?
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4233925.html
Copyright © 2011-2022 走看看