• POJ2486 Apple Tree 【树上背包】


    一句话题意:一棵树,一共n个点,每个点上有一个权值,求从1出发,走k步,最多能遍历到的权值。可以往回走。

    第一(二)道树上背包题,先是看了dalao的题解,改了一点就过样例了。然而....TLE??? 改了挺久发现由于多组数据且没有“0 0”的输入,如果不在读入的时候加“~”或“EOF”就会死循环,从而导致TLE。

    状态设计:设f[i][j][0/1]为以i为根的子树上,走j步,能得到的最大权值(0/1的表示会在转移方程中描述) 考虑:(此处参考dalao@zubizakeli ,侵删qwq)每个节点在最终答案中的类型:1,不经过;2,经过但不返回;3,经过且返回 (返回的定义是最终的停止节点不位于该节点的子树中) 那么可以进行转移:

    之后便是一些细节问题:给数组赋初值(从0开始!走0步),更新head数组。

    实现还是比较简单的啦。

    code

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 
     5 using namespace std;
     6 
     7 int n,k,tot;
     8 int w[300],head[300];
     9 int f[300][200][3]; 
    10 struct node{
    11     int to,next,val;
    12 }edge[300];
    13 
    14 void add(int x,int y)
    15 {
    16     edge[++tot].to=y;
    17     edge[tot].next=head[x];
    18     head[x]=tot;
    19 }
    20 
    21 void read(int &x)
    22 {
    23     x=0;
    24     char ch=getchar();
    25     bool flag=false;
    26     while(ch<'0'||ch>'9') flag|=(ch=='-'),ch=getchar();
    27     while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    28     x=flag ? -x : x;
    29 }
    30 
    31 void TreeDp(int u,int fa)
    32 {
    33     for(int i=0;i<=k;i++) f[u][i][1]=w[u],f[u][i][0]=w[u];
    34     for(int i=head[u];i;i=edge[i].next)
    35     {
    36         int v=edge[i].to;
    37         if(v==fa) continue;
    38         TreeDp(v,u);
    39         for(int kk=k;kk>=0;kk--)
    40         for(int j=0;j<=kk;j++)
    41         {
    42             if(kk>=j+2) f[u][kk][0]=max(f[u][kk][0],f[v][j][0]+f[u][kk-j-2][0]);
    43             if(kk>=j+2) f[u][kk][1]=max(f[u][kk][1],f[v][j][0]+f[u][kk-j-2][1]);
    44             if(kk>=j+1) f[u][kk][1]=max(f[u][kk][1],f[v][j][1]+f[u][kk-j-1][0]);
    45         }
    46     }
    47 }
    48 
    49 void init()
    50 {
    51     memset(f,0,sizeof(f));
    52     memset(head,0,sizeof(head));
    53     tot=0;
    54 } 
    55 
    56 int main()
    57 {
    58     while(scanf("%d%d",&n,&k)!=EOF)
    59     {
    60         for(int i=1;i<=n;i++) read(w[i]);
    61         for(int i=1;i<=n-1;i++)
    62         {
    63             int x=0,y=0;
    64             read(x),read(y);
    65             add(x,y),add(y,x);
    66         }
    67         TreeDp(1,-1);
    68         printf("%d
    ",max(f[1][k][0],f[1][k][1]));
    69         init();
    70     }
    71     return 0;
    72 }
    View Code

    小结:分类讨论常常也是解题重要的突破口呐。

  • 相关阅读:
    金蝶k3 显示BOS序时簿并返回选中的值
    金蝶K3bos插件操作另一张单据
    H2.64的远程回放--开篇
    监控外网访问的几种方式
    ilbc编解码
    windows系统上安装与使用Android NDK r5 (转)
    安卓与PC网络对接实现视频实时播放
    WDR7500 花生壳问题
    要确保任何一次员工的晋升都符合公司的利益
    关于“部门建设”
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9452445.html
Copyright © 2020-2023  润新知