zoukankan      html  css  js  c++  java
  • HDU 1011 Starship Troopers 树形+背包dp

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

     
    题意:每个节点有两个值bug和brain,当清扫该节点的所有bug时就得到brain值,只有当父节点被清空时,才可以清扫它          的子节点,而清扫需要一定的人员。给定M个人员,N个结点的树,求最大brain和
     
    这看起来是一道非常简单的背包dp
    但是
    写完提交wa之后,我发现这道题,并不简单!因为他的题意并不是完全和我找到的题意一样(我承认我语文很差劲所以随便找个题解看题意。。),题目中要求每一个人是不能往回走的,所以节点bug值为0时也不能随意收集brain,一个人员只能收集一条链。当然0个人的时候不管怎么样都收集不到brain直接特判。
    这个问题可以通过一个非常之骚的操作解决,操作如下
    f[a][b]代表以a点为根的子树布置b个人能得到的最大brain的和
    1 for(int k=m;k>=bu[x];k--){
    2                 for(int j=1;j+k<=m;j++){//注意这个地方从1开始
    3                     f[x][k+j]=max(f[x][k+j],f[x][k]+f[y][j]);
    4                 }
    5 }
    View Code

    j从1开始循环完美避免了不给下面的路分配人却得到brain值的事情发生,然后就可以ac了。。。

    但是并没有ac。。为什么呢。。。因为我,没有把写好的清空数据函数放到主程序里。。。

    然后我wa了8次。。。引以为戒。
    代码:
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 const int maxn=110;
     8 const double eps=1e-8;
     9 const int modn=45989;
    10 int n,m;
    11 struct nod{
    12     int next,y;
    13 }e[maxn*2];
    14 int bu[maxn]={},bra[maxn]={},head[maxn]={},tot=0;
    15 bool vis[maxn]={};
    16 int f[maxn][maxn]={};
    17 void init(int x,int y){
    18     e[++tot].y=y;
    19     e[tot].next=head[x];
    20     head[x]=tot;
    21 }
    22 void dfs(int x){
    23     vis[x]=1;
    24     int y;
    25     for(int i=bu[x];i<=m;i++){
    26         f[x][i]=bra[x];
    27     }
    28     for(int i=head[x];i;i=e[i].next){
    29         y=e[i].y;
    30         if(!vis[y]){
    31             dfs(y);
    32             for(int k=m;k>=bu[x];k--){
    33                 for(int j=1;j+k<=m;j++){
    34                     f[x][k+j]=max(f[x][k+j],f[x][k]+f[y][j]);
    35                 }
    36             }
    37         }
    38     }
    39 }
    40 void yu(){
    41     tot=0;memset(f,0,sizeof(f));
    42     memset(head,0,sizeof(head));
    43     memset(vis,0,sizeof(vis));
    44 }
    45 int main(){
    46     for(;;){
    47         yu();
    48         scanf("%d%d",&n,&m);
    49         if(n==-1||m==-1){
    50             break;
    51         }
    52         for(int i=1;i<=n;i++){
    53             scanf("%d%d",&bu[i],&bra[i]);
    54             bu[i]=(bu[i]+19)/20;
    55         }
    56         int x,y;
    57         for(int i=1;i<n;i++){
    58             scanf("%d%d",&x,&y);
    59             init(x,y);init(y,x);
    60         }
    61         if(m==0){
    62             printf("0
    ");
    63             continue;
    64         }
    65         dfs(1);
    66         printf("%d
    ",f[1][m]);
    67     }
    68     return 0;
    69 }
    View Code
  • 相关阅读:
    古代军队的官的从大到小的排序
    [转]DAO、RDO、ADO、OLE DB 、ODBC and JDB
    JSP页面之间参数传递中文出现乱码
    重置VS2008插件环境
    PB7中调用VC6的DLL
    Visual Studio统计有效代码行数
    php.ini 中文版
    IDEA Plugin JB* Components
    [转]你还在为怎么查看字节码指令而担忧吗?
    战地2, 2142解决Win10运行闪退问题
  • 原文地址:https://www.cnblogs.com/137shoebills/p/7786505.html
Copyright © 2011-2022 走看看