zoukankan      html  css  js  c++  java
  • 【树形背包(边)】【调试毒瘤】LuoGu P2015 二叉苹果树

    这道题的状态转移方程极其好想,不会可以回家洗洗睡了

    dp[now][j]=max(dp[now][j],dp[now][j-k-1]+dp[to][k]+edge[i].val)

    但是!!

    调试极其毒瘤!

    本以为背包背的是边和点差不多,结果发现恶心至极

     1 int DP(int now,int fa)
     2 {
     3     int sum=0;
     4     for(int i=head[now],to;i!=-1;i=edge[i].nxt)
     5     {
     6         to=edge[i].to;
     7         if(to==fa)continue;
     8         leaf=0;
     9         int tt=DP(to,now);
    10         sum+=tt;        
    11         for(int j=sum;j>=0;j--)
    12         {
    13             for(int k=0;k<=tt-1;k++)
    14             {
    15                 if(j>=k+1)dp[now][j]=max(dp[now][j],dp[now][j-k-1]+dp[to][k]+edge[i].val);
    16             }
    17         }
    18     }
    19     return sum+1;
    20 }

    来让我们慢慢分析为什么要这么写,

    1.那个sum是什么

      sum返回的其实是点的数量(这样好理解),或者理解成子树的边的个数+1也行,为什么要+1,因为对于叶节点,它下面没有边,返回的不可能是0,只能是1,所以只能加一

    2.枚举范围是为什么??

      首先看j的范围,我什么是sum呢?记得sum是什么吗,是子树边,加一,刚好是父节点要选的,所以可以直接就是sum,

      看k的范围,为什么是tt-1,也是因为sum的意义,减1了才是子树的边数量

      那么为什么是j-k-1呢,因为如果你在当前子节点选了k个,同时你也把根节点和子节点的边也选了,所以实际上选的是k+1个边,

      然后j>=k+1就是怕超范围

    结束QAQ

    上代码

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #define N 111
     5 #define _ 0
     6 using namespace std;
     7 int n,q,u,v,w,cnt=1;
     8 int head[N],dp[N][N];
     9 struct star{int to,nxt,val;}edge[N*2];
    10 inline void add(int u,int v,int w)
    11 {
    12     edge[cnt].nxt=head[u];
    13     edge[cnt].to=v;
    14     edge[cnt].val=w;
    15     head[u]=cnt++;    
    16 }
    17 int DP(int now,int fa)
    18 {
    19     int sum=0;
    20     for(int i=head[now],to;i!=-1;i=edge[i].nxt)
    21     {
    22         to=edge[i].to;
    23         if(to==fa)continue;
    24         int tt=DP(to,now);
    25         sum+=tt;        
    26         for(int j=min(sum,q);j>=0;j--)
    27         {
    28             for(int k=0;k<=tt-1;k++)
    29             {
    30                 if(j>=k+1)dp[now][j]=max(dp[now][j],dp[now][j-k-1]+dp[to][k]+edge[i].val);
    31             }
    32         }
    33     }
    34     return sum+1;
    35 }
    36 int main()
    37 {
    38     memset(head,-1,sizeof(head));
    39     scanf("%d%d",&n,&q);
    40     for(int i=1;i<n;i++)
    41         scanf("%d%d%d",&u,&v,&w),
    42         add(u,v,w),add(v,u,w);
    43     DP(1,-1);        
    44     printf("%d",dp[1][q]);
    45     return ~~(0^_^0);
    46 }
  • 相关阅读:
    关于 HTML5 的 11 个让人难以接受的事实
    【转】zookeeper 的监控工具
    arm+linux 裸机环境搭建之安装工具篇(eclipse)
    Unity 利用NGUI2.6.3做技能冷却的CD效果
    spring boot打包文件后,报错No such file or directory
    机器学习实战读书笔记(3)朴素贝叶斯
    机器学习实战读书笔记(2)决策树
    机器学习实战读书笔记(1)
    No operations allowed after connection closed--转
    简单理解Socket
  • 原文地址:https://www.cnblogs.com/Qin-Wei-Kai/p/10110586.html
Copyright © 2011-2022 走看看