zoukankan      html  css  js  c++  java
  • hdu 1561 树形dp+分组背包

    题意:就是给定n个点,每个地点有value[i]的宝物,而且有的宝物必须是另一个宝物取了才能取,问取m个点可以获得的最多宝物价值。

    一个子节点就可以返回m个状态,每个状态表示容量为j(j<=m)时选最多的宝物,而一个子节点中只可以选择一个状态进行转移,每个节点有若干个子节点,问题就转换为分组背包,几个子节点就是几个分组背包,体积是选几个地点,价值是宝物价值。      

    状态转移方程: dp[v][1] = Money[v]; (v为叶子节点)
                       dp[v][j] = max(dp[v][j],dp[v][j-i] + dp[k][i] );(v为非叶子节点,j表示用户个数,i为容量,k为v的子节点,)

    是不是分组背包都无所谓,直接按照方程来了,可能j的值是需要逆向枚举用到背包吧

     2015-05-11:

    和bug那题一模一样,我会乱说?链接:点我

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<queue>
     7 #include<map>
     8 using namespace std;
     9 #define MOD 1000000007
    10 const int INF=0x3f3f3f3f;
    11 const double eps=1e-5;
    12 typedef long long ll;
    13 #define cl(a) memset(a,0,sizeof(a))
    14 #define ts printf("*****
    ");
    15 const int MAXN=1005;
    16 int dp[MAXN][MAXN],val[MAXN],head[MAXN];
    17 int n,m,tt,tot;
    18 struct Edge
    19 {
    20     int to,next;
    21 }edge[MAXN];
    22 void addedge(int u,int v)
    23 {
    24     edge[tot].to=v;
    25     edge[tot].next=head[u];
    26     head[u]=tot++;
    27 }
    28 void init()
    29 {
    30     memset(head,-1,sizeof(head));
    31     tot=0;
    32     memset(dp,0,sizeof(dp));
    33 }
    34 void dfs(int u,int pre)
    35 {
    36     dp[u][1]=val[u];
    37     for(int i=head[u];i!=-1;i=edge[i].next)
    38     {
    39         int v=edge[i].to;
    40         if(v==pre)  continue;
    41         dfs(v,u);
    42         for(int j=m;j>=1;j--)
    43         {
    44             for(int k=1;j-k>=1;k++)
    45             {
    46                 dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]);
    47             }
    48         }
    49     }
    50 }
    51 int main()
    52 {
    53     int i,j,k;
    54     #ifndef ONLINE_JUDGE
    55     freopen("1.in","r",stdin);
    56     #endif
    57     while(scanf("%d%d",&n,&m)!=EOF)
    58     {
    59         if(n==0&&m==0)  break;
    60         init();
    61         for(i=1;i<=n;i++)
    62         {
    63             int a;
    64             scanf("%d%d",&a,&val[i]);
    65             addedge(a,i);
    66         }
    67         m++;    //多了一个0节点
    68         val[0]=0;
    69         dfs(0,-1);
    70         printf("%d
    ",dp[0][m]);
    71     }
    72 }
  • 相关阅读:
    fianl关键字和static关键字
    jdk的安装
    this关键字和super关键字
    Java 数组
    网络通信知识复习
    Linux 下执行本目录的可执行文件(命令)为什么需要在文件名前加“./”
    CentOS 7 下安装 teamviewer 13
    我的 Putty 配色方案
    在 Mac OS X 下,如何向 sudoers 文件添加新用户
    Windows 7 下使用 pandoc 转换文档格式
  • 原文地址:https://www.cnblogs.com/cnblogs321114287/p/4325352.html
Copyright © 2011-2022 走看看