• hdu1011(树形背包)


    hdu1011 http://acm.hdu.edu.cn/showproblem.php?pid=1011

    给定n个洞穴和m个士兵(每个士兵能消灭20个bugs)

    然后给定每个洞穴的bugs数量(背包的费用)和brain的数量(背包的价值)

    然后给定n-1条边,使得n个洞穴形成一课树

    问能取得的brain数量的最大值。

    思路:其实就是在树上面进行背包问题的求解,只不过是有依赖的背包(儿子要选,当且仅当父亲也被选)

    普通的01背包是这样

    for(i=每件物品)

      for(j=每个容量)

         dp[i][j] = max(dp[i-1][j],dp[i-1][j-c[i]]+w[i]);

    即对于每个物品,求出各个容量的背包对于第i件物品处理完之后的最大值。

    那么在树上面进行背包问题,同样要是这样。

    第一个循环:

      但是因为背包是树形的,所以不能用循环来遍历背包,要用dfs来进行遍历

    第二个循环:

      因为是有依赖的背包问题,儿子要选,当且仅当父亲也被选。所以我们要枚举父亲的容量和儿子的容量进行状态转移(即两重循环)

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <stdlib.h>
     4 #include <algorithm>
     5 #include <iostream>
     6 #include <queue>
     7 #include <stack>
     8 #include <vector>
     9 #include <map>
    10 #include <set>
    11 #include <string>
    12 #include <math.h>
    13 using namespace std;
    14 typedef long long LL;                   
    15 const int INF = 1<<30;
    16 const int N = 100+10;
    17 struct Cave
    18 {
    19     int bugs,brain;
    20 }cave[N];
    21 int dp[N][N];
    22 struct Edge
    23 {
    24     int v,next;
    25 }g[N<<1];
    26 int head[N],e;
    27 
    28 /*
    29 背包?
    30 有依赖的背包
    31 容量为m
    32 费用为bugs的数量, 价值为brain的数量
    33 对于每个洞穴,选或者不选
    34 这个洞穴要选,当且仅当父亲被选
    35 */
    36 bool vis[N];
    37 int m;
    38 void dfs(int u, int fa)
    39 {
    40     vis[u] = true;
    41     int t = (cave[u].bugs+19)/20;
    42     for(int i=t; i<=m; ++i)
    43         dp[u][i] = cave[u].brain;
    44     for(int i=head[u]; i!=-1; i=g[i].next)
    45     {
    46         int v = g[i].v;
    47         if(vis[v]) continue;
    48         dfs(v,u);
    49         for(int j=m; j>=t; --j)//必须从后往前推??? 由转移方程可以看出,前面的状态依赖于后面的状态,所以要求出后面的状态
    50             for(int k=1; k+j<=m; ++k)//所有可能的情况都要枚举,然后求出最大值
    51                 dp[u][j+k] = max(dp[u][j+k],dp[u][j]+dp[v][k]);
    52         
    53         
    54     }
    55 }
    56 void init(int n)
    57 {
    58     for(e=0; e<=n; ++e)
    59     {
    60         head[e] = -1;
    61         vis[e] = false;
    62     }
    63     e = 0;
    64 }
    65 void addEdge(int u, int v)
    66 {
    67     g[e].v = v;
    68     g[e].next = head[u];
    69     head[u] = e++;
    70 }
    71 int main()
    72 {
    73     int n,i,u,v;
    74     while(scanf("%d%d",&n,&m),n!=-1)
    75     {
    76         init(n);
    77         for(i=1; i<=n; ++i)
    78             scanf("%d%d",&cave[i].bugs,&cave[i].brain);
    79         for(i=1; i<n; ++i)
    80         {
    81             scanf("%d%d",&u,&v);
    82             addEdge(u,v);
    83             addEdge(v,u);
    84         }
    85         if(m==0)
    86         {
    87             puts("0");
    88             continue;
    89         }    
    90         memset(dp,0,sizeof(dp));
    91         dfs(1,-1);
    92         printf("%d
    ",dp[1][m]);
    93     }
    94     return 0;
    95 }
    View Code

    样例:

  • 相关阅读:
    巡风安装配置 -windows
    Struts2-052 RCE CVE-2017-9805
    CVE-2017-12615和CVE-2017-12616
    Nmap使用指南
    理解HTTP协议
    缓慢拒绝服务攻击- slowloris.pl
    SSL&TLS渗透测试
    Nmap版本检测
    Protocol Buffer学习教程之编译器与类文件(三)
    64位Windows系统下32位应用程序连接MySql
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4437436.html
Copyright © 2020-2023  润新知