zoukankan      html  css  js  c++  java
  • 【DP专题】——洛谷P1273有线电视网

    树形dp板子。

    传送门:GO


      用dp[i][j]表示以i为根的子树中选取j个观众能赚到的最多钱(经典模型)。

      那么,dp[i][j+k]=max(dp[son[i]][k]+dp[i][j]-w,dp[i][j+k]),意思是说,如果在子树中选了k个观众,那么答案就是(当前只选了j个的情况+选子树中k个观众的情况-这一段代价)。

      确定一下枚举上界:初步估计,每一次选择观众量就是当前子树所含观众量,所以将dfs设计成返回子树所含观众量的类型,就可以处理枚举上界了。

      对于节点u,外层枚举上界就是u的所有子树的前缀(需动态更新),内层上界就是当前子树大小。

      考虑到转移式子,少的观众会对多的观众造成影响,所以倒序枚举,从多到少,就不会造成多余影响了。

      其余的见代码吧。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int read(){
     4     int x=0,f=1;
     5     char c=getchar();
     6     while(!isdigit(c)){
     7         if(c=='-') f=-1;
     8         c=getchar();
     9     }
    10     while(isdigit(c)){
    11         x=x*10+c-'0';
    12         c=getchar();
    13     }
    14     return x*f;
    15 }
    16 const int N=3010;
    17 int n,m,cnt;
    18 int head[N<<1];
    19 int mon[N],f[N][N];
    20 struct edge{int to,next,w;}e[N<<1];
    21 void addedge(int from,int to,int w){e[++cnt]=(edge){to,head[from],w};head[from]=cnt;}
    22 int dfs(int u){
    23     if(u>n-m){
    24         f[u][1]=mon[u];
    25         return 1;
    26     }
    27     int upz=0;
    28     for(int i=head[u];i;i=e[i].next){
    29         int v=e[i].to,w=e[i].w;
    30         int now=dfs(v);
    31         for(int j=upz;j>=0;j--){
    32             for(int k=0;k<=now;k++){
    33                 f[u][j+k]=max(f[u][j+k],f[u][j]+f[v][k]-w);
    34             }
    35         }
    36         upz+=now;
    37     }
    38     return upz;
    39 }
    40 int main(){
    41     n=read();m=read();
    42     for(int i=1,k;i<=n-m;i++){
    43         k=read();
    44         for(int j=1;j<=k;j++){
    45             int x=read(),y=read();
    46             addedge(i,x,y);
    47         }
    48     }
    49     for(int i=n-m+1;i<=n;i++) mon[i]=read();
    50     memset(f,-0x3f,sizeof(f));
    51     for(int i=1;i<=n;i++) f[i][0]=0;
    52     dfs(1);
    53     for(int i=m;i>0;i--){
    54         if(f[1][i]>=0){
    55             printf("%d",i);
    56             return 0;
    57         }
    58     }
    59     return 0;
    60 } 
    ——抓住了时间,却不会利用的人,终究也逃不过失败的命运。
  • 相关阅读:
    homebrew
    Flutter状态管理之provide和provider的使用区别
    Flutter Bloc状态管理 简单上手
    Flutter 路由传入中文参数报错无法push问题
    Flutter 一些常用第三方库、插件
    js替换字符串中的空格,换行符 或 替换成<br>
    Flutter状态管理Provider,简单上手
    Flutter Resolving dependencies...很慢解决办法
    Flutter布局--appbar导航栏和状态栏
    Flutter运行报错 `kernel_snapshot for errors` 解决方案
  • 原文地址:https://www.cnblogs.com/Nelson992770019/p/11580785.html
Copyright © 2011-2022 走看看