zoukankan      html  css  js  c++  java
  • POJ1155--TELE ---树形DP

    题意:给你一棵树,树的1号节点是电视台,2~n-m号节点是转播站,剩下的m个点是用户。点到点之间传递信号要消耗钱,最后一行给你能从每个用户收取的钱。然后问你在不亏本的情况下最多可以让多少的用户看到电视。

    状态方程设为dp[i][j]表示,由点i开始传送,且让j名观众能够收到信号的情况下最大的利润

    在搜索过程中,先把整棵树都跑完,处理出数组h[i] 表示以i为根节点的子树里有h[i]个观众。在递归到观众节点时,把该观众的收入存到dp[i][1]里。之后枚举i,j,k的值,分别表示走第几棵子树、递归到此最多能有几个观众、父亲节点下,该子树的前面的子树负责k个用户且这个子树负责j-k个用户。

    如果j==k的话,表示不需要当前i这个子树来分担观众数,所以消耗是不需要加上父节点到该节点的那条花费的。最后遍历一遍,得到答案。

    代码如下:

    #include<iostream>
    #include<vector>
    #include<queue>
    #include<string.h>
    #include<stdio.h>
    using namespace std;
    #define p pair<int,int>
    const int inf=-2100000000;
    vector<p> a[100050];
    int dp[3010][3010],c[3010],h[3010];
    int ans,mark; 
    int solve(int u)
    {
        if(a[u].size()==0)
        {
            dp[u][1]=c[u];
            h[u]=1;
            return 0;
        }
    
        for(int i=0;i<a[u].size();i++) 
        {
            solve(a[u][i].first);
        }
        int son=0;
        for(int i=0;i<a[u].size();i++)
        {
            for(int j=son+h[a[u][i].first];j>=1;j--)
            {
                for(int k=0;k<=son&&k<j;k++)
                {
                    if(dp[u][k]!=inf&&dp[a[u][i].first][j-k]!=inf)
                    {
                        if(k!=j) dp[u][j]=max(dp[u][j],dp[u][k]+dp[a[u][i].first][j-k]-a[u][i].second);
                        else dp[u][j]=max(dp[u][j],dp[u][k]+dp[a[u][i].first][j-k]);
                    }
                }
            }
            son+=h[a[u][i].first];
        }    
        h[u]=son;
    
    }
    int main()
    {
        int i,j,k,l,x,y,n,huan,m;
        scanf("%d%d",&n,&m);
        for(i=1;i<=n-m;i++)
        {
            scanf("%d",&l);
            while(l--)
            {
                scanf("%d%d",&x,&y);
                a[i].push_back(p(x,y));
                //cout<<a[i][a[i].size()-1].first<<" "<<a[i][a[i].size()-1].second<<endl;
            }
            
        }for(i=n-m+1;i<=n;i++) scanf("%d",&c[i]);
        for(i=1;i<=n;i++)
        {
            dp[i][0]=0;
            for(j=1;j<=m;j++) dp[i][j]=inf;
        }
        solve(1);
        int mx=0;
        for(i=0;i<=m;i++) if(dp[1][i]>=0) mx=i;
        cout<<mx<<endl;
        
    }
  • 相关阅读:
    Springboot + Caffeine 实现本地缓存
    springboot + mybatis-plus + sharding-jdbc 实现单库分表
    工厂模式+策略模式 使用
    JAVA 金额自动除以100,精确到分
    spring aop + 自定义注解实现本地缓存
    springboot 使用 retry重试机制
    Mybatis-plus 自动注入公共字段
    docker 安装kafka
    ES 实现聚合分页
    Authentication token manipulation error 及 mongodb WiredTigerLAS.wt 文件过大问题
  • 原文地址:https://www.cnblogs.com/wsblm/p/10730191.html
Copyright © 2011-2022 走看看