• P1273 有线电视网


    状态表示:
    (dp[u][j]):以(u)为根的子树上有(j)个用户时的最大收益。计算结束后,使(dp[1][i] ge 0)的最大(i)就是答案。

    状态转移:

    [dp[u][j] = max(dp[u][j], dp[u][j-k] + dp[v][k] - w) ]

    边界:
    (f[u][0]=0)(f[leaf][1]=pay[leaf])

    注意点

    枚举用户数和转移时需要小优化,而不能直接从总的用户数开始枚举,否则会超时。

    const int N=3010;
    vector<PII> g[N];
    int f[N][N];
    int pay[N];
    int n,m;
    
    int dfs(int u)
    {
        f[u][0]=0;
        
        if(u > n-m)  // 叶子
        {
            f[u][1]=pay[u];
            return 1;
        }
        
        int sum=0;
        for(int i=0;i<g[u].size();i++)
        {
            int v=g[u][i].fi,w=g[u][i].se;
            int t=dfs(v);
            sum+=t;
            for(int j=sum;j>=0;j--)
                for(int k=0;k<=min(t,j);k++)
                    f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]-w);
        }
        
        return sum;
    }
    
    int main()
    {
        memset(f,-0x3f,sizeof f);
        
        cin>>n>>m;
    
        for(int i=1;i<=n-m;i++)
        {
            int k;
            cin>>k;
            while(k--)
            {
                int a,c;
                cin>>a>>c;
                g[i].pb({a,c});
            }
        }
    
        for(int i=n-m+1;i<=n;i++) cin>>pay[i];
    
        dfs(1);
    
        for(int i=m;i>=1;i--)
            if(f[1][i] >= 0)
            {
                cout<<i<<endl;
                break;
            }
        //system("pause");
        return 0;
    }
    
  • 相关阅读:
    多线程(一)
    Interface
    Abstract
    面向对象
    字符串比对(10分)
    快递费用计算(7分)
    练习7-8 方阵循环右移 (20分)
    习题4-11 兔子繁衍问题 (15分)
    一道题理解穷举/贪心/爬山/遗传/退火/蚁群算法
    华为暑期测试实习生面经(2020.06)
  • 原文地址:https://www.cnblogs.com/fxh0707/p/14641259.html
Copyright © 2020-2023  润新知