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 } 
    ——抓住了时间,却不会利用的人,终究也逃不过失败的命运。
  • 相关阅读:
    从句分析
    artDialog ( v 6.0.2 ) content 参数引入页面 html 内容
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 11 盛最多水的容器
    Java实现 LeetCode 11 盛最多水的容器
  • 原文地址:https://www.cnblogs.com/Nelson992770019/p/11580785.html
Copyright © 2011-2022 走看看