zoukankan      html  css  js  c++  java
  • csu 2014 summer training day 4 树形dp升阶

    POJ 1155

    题意:电视台发送信号给很多用户,每个用户有愿意出的钱,电视台经过的路线都有一定费用,求电视台不损失的情况下最多给多少用户发送信号。

    要知道用户都在叶子节点,费用消耗在使用选择的路径上,每条路径的使用费用给出,每个用户支付的费用给出。

    输入:N为总节点数,M为用户数,1为电视台, 2 to N-M 是中转站,N-M+1到N是潜在用户

    对于1到N-M的中继点,给出连接的点的个数K,K对(A,C)表示连接到A点,这条路径的费用是C

    最后是M个整数,表示用户支付的费用

    分析:

    int num[maxn];//记录每个节点下面的总用户数
    int dp[maxn][maxn];//i:i的子树中,j:节点下面的使用用户数,能达到的最大的剩余利润
    //dp:最大剩余利润:线路费用-使用用户支付的费用
    相当于树形背包:
    dp[u][j+k]=max(dp[u][j+k],temp[j]+dp[v][k]-len[u][i]);
    temp[j]表示原来的dp[u][j]
    对于搜索出来的一棵树,对于它的孩子,可以选择加还是不加,其中len[u][i]恰好表示u到当前选择的v的代价

    完整写法:
            for(int j=0;j<=num[u];j++){
                temp[j]=dp[u][j];
            }
            for(int j=0;j<=num[u];j++){
                for(int k=1;k<=num[v];k++){//注意k!=0,否则多减少了i
                    dp[u][j+k]=max(dp[u][j+k],temp[j]+dp[v][k]-len[u][i]);
                }
            }
            num[u]+=num[v];

    代码:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <vector>
     5 #define maxn 3100
     6 #define INF 99999999
     7 using namespace std;
     8 
     9 int num[maxn];//记录每个节点下面的总用户数
    10 int dp[maxn][maxn];//i:处理的节点数,j:节点下面的使用用户数
    11 //dp:最大剩余利润:线路费用-使用用户支付的费用
    12 int N,M;
    13 vector<int>G[maxn];
    14 vector<int>len[maxn];
    15 int temp[maxn];
    16 void dfs(int u,int fa){
    17 
    18 //    cout<<"u="<<u<<endl;
    19 //    for(int i=0;i<G[u].size();i++){
    20 //        int v=G[u][i];
    21 //        if (v==fa) continue;
    22 //        dfs(v);
    23 //        num[u]+=num[v];
    24 //    }
    25 //    //用子节点更新u
    26 //    int sum=0;
    27 //    for(int i=0;i<G[u].size();i++){//依次枚举下层节点
    28 //        int v=G[u][i];
    29 //        if (v==fa) continue;
    30 //        for(int j=0;j<=sum;j++){//设置这个的原因是,仔细看下面,原本的dp[u][j]已经被覆盖了
    31 //            temp[j]=dp[u][j];
    32 //        }
    33 //        for(int j=0;j<=sum;j++){
    34 //            for(int k=0;k<=num[v];k++){
    35 //                dp[u][j+k]=max(dp[u][j+k],temp[j]+dp[v][k]-len[u][i]);
    36 //            }
    37 //        }
    38 //        sum+=num[v];
    39 //    }
    40 //我们可以看出,上面两部分可以和在一起写,而且每次更新的num[u]就是sum
    41 
    42     dp[u][0]=0;
    43     for(int i=0;i<G[u].size();i++){
    44         int v=G[u][i];
    45         if (v==fa) continue;
    46         dfs(v,u);
    47         for(int j=0;j<=num[u];j++){
    48             temp[j]=dp[u][j];
    49         }
    50         for(int j=0;j<=num[u];j++){
    51             for(int k=1;k<=num[v];k++){//注意k!=0,否则多减少了i
    52                 dp[u][j+k]=max(dp[u][j+k],temp[j]+dp[v][k]-len[u][i]);
    53             }
    54         }
    55         num[u]+=num[v];
    56     }
    57     return ;
    58 }
    59 void solve(){
    60     for(int i=M;i>=0;i--){
    61         if (dp[1][i]>=0) {
    62             printf("%d
    ",i);
    63             break;
    64         }
    65     }
    66     return ;
    67 }
    68 int main(){
    69     while(~scanf("%d%d",&N,&M)){
    70         for(int i=0;i<=N;i++) G[i].clear();
    71         for(int i=1;i<=N-M;i++){
    72             int k;
    73             scanf("%d",&k);
    74             for(int j=1;j<=k;j++){
    75                 int v,c;
    76                 scanf("%d%d",&v,&c);
    77                 G[i].push_back(v);
    78                 len[i].push_back(c);
    79             }
    80         }
    81         memset(num,0,sizeof(num));
    82         for(int i=0;i<=N;i++){
    83             for(int j=0;j<=N;j++) dp[i][j]=-INF;
    84         }
    85         for(int i=N-M+1;i<=N;i++){
    86             scanf("%d",&dp[i][1]);
    87             num[i]=1;
    88         }
    89         dfs(1,-1);
    90         solve();
    91     }
    92     return 0;
    93 }
    View Code

    POJ 2486

    题意:Wshxzt从根节点1开始在苹果树上游历,树上的每个节点都会存在apple[i]个苹果,从一个节点到它的邻节点耗费步数1。现在Wshxzt可以步行step步,求她可以得到的最大苹果数量。

    输入:N节点数,K最大步数,每个节点的苹果数,N-1条边

    分析:

    代码:

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<string.h>
     4 #include<vector>
     5 #define MAXN 110
     6 #define MAXK 220
     7 using namespace std;
     8 
     9 vector<int>G[MAXN];
    10 int anum[MAXN];
    11 int dp[MAXN][MAXK][2];
    12 int N,K;
    13 int temp[MAXN];
    14 void dfs(int u,int fa){
    15     dp[u][0][1]=anum[u];
    16     dp[u][0][0]=anum[u];
    17     for(int i=0;i<G[u].size();i++){
    18         int v=G[u][i];
    19         if (v==fa) {
    20             continue;
    21         }
    22         dfs(v,u);
    23         for(int j=K;j>=0;j--){
    24             for(int t=1;t<=j;t++){
    25                 dp[u][j][0]=max(dp[u][j][0],dp[v][t-1][0]+dp[u][j-t][1]);
    26                 if (t==1) continue;
    27                 dp[u][j][0]=max(dp[u][j][0],dp[v][t-2][1]+dp[u][j-t][0]);
    28                 dp[u][j][1]=max(dp[u][j][1],dp[v][t-2][1]+dp[u][j-t][1]);
    29             }
    30         }
    31     }
    32 
    33     return ;
    34 }
    35 int main(){
    36     while(~scanf("%d%d",&N,&K)){
    37         for(int i=1;i<=N;i++){
    38             scanf("%d",&anum[i]);
    39         }
    40         for(int i=0;i<=N;i++) G[i].clear();
    41         for(int i=1;i<=N-1;i++){
    42             int u,v;
    43             scanf("%d%d",&u,&v);
    44             G[u].push_back(v);
    45             G[v].push_back(u);
    46         }
    47         memset(dp,0,sizeof(dp));
    48         for(int i=0;i<=N;i++){
    49             for(int j=0;j<=K;j++) dp[i][j][0]=dp[i][j][1]=anum[i];
    50         }
    51         dfs(1,-1);
    52         printf("%d
    ",dp[1][K][0]);
    53     }
    54     return 0;
    55 }
    View Code

    POJ 1947

     

    POJ 1848

    POJ 1655

  • 相关阅读:
    Flutter 布局类组件:简介
    Flutter 基础组件:进度指示器
    Flutter 基础组件:单选框和复选框
    Flutter 基础组件:图片和Icon
    Flutter 基础组件:按钮
    Flutter 基础组件:文本、字体样式
    Flutter 基础组件:状态管理
    Flutter 基础组件:Widget简介
    网络编程之TCP
    入门多线程
  • 原文地址:https://www.cnblogs.com/little-w/p/3873722.html
Copyright © 2011-2022 走看看