• 有线电视网


    传送门

    仍然是一道标准的树形DP。

    我们其实不必纠结到底剩余的钱数是多少,那并不重要,我们只关心其是否大于0。而且我们其实要求的是能连接的最大用户数。

    用dp[i][j]表示在第i个节点连接了j个客户的最大利润。那么得到:

    dp[i][j] = max(dp[i][j],dp[i][j-k] + dp[t][k] - e[i].v);

    之后又可以做了……(好像这样的树形DP推出方程即结束)

    注意初值要设成-INF(因为有负数)。还是因为背包的思想,我们在枚举第一维(当前点连接顾客数)的时候要倒着枚举。

    看一下代码。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<set>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    typedef long long ll;
    const int M = 10005;
    const int INF = 1000000009;
    
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') op = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            ans *= 10;
            ans += ch - '0';
            ch = getchar();
        }
        return ans * op;
    }
    
    struct edge
    {
        int next,to,v;
    }e[10005];
    
    int a[10005],n,m,dp[3005][3005],x,y,ecnt,head[10005];
    
    void add(int x,int y,int z)
    {
        e[++ecnt].to = y;
        e[ecnt].v = z;
        e[ecnt].next = head[x];
        head[x] = ecnt;
    }
    
    int dfs(int x,int fa)
    {
        dp[x][0] = 0;
        if(x > n-m)
        {
            dp[x][1] = a[x];
            return 1;
        }
        int tot = 0;
        for(int i = head[x];i;i = e[i].next)
        {
            int t = e[i].to;
            if(t == fa) continue;
            int gg = dfs(t,x);
            tot += gg;
            per(j,tot,1)
            {
                rep(k,0,gg) dp[x][j] = max(dp[x][j],dp[t][k] + dp[x][j-k] - e[i].v);
            }
        }
        return tot;
    }
    int main()
    {
        n = read(),m = read();
        rep(i,1,n)
        rep(j,1,n) dp[i][j] = -INF;
        rep(i,1,n-m)
        {
            int g = read();
            rep(j,1,g) x = read(),y = read(),add(i,x,y),add(x,i,y);
        }
        rep(i,n-m+1,n) a[i] = read();
        dfs(1,0);
        per(i,m,0) 
        {
            if(dp[1][i] >= 0)
            {
                printf("%d
    ",i);
                break;
            }
        }
        return 0;
    }
  • 相关阅读:
    两数相加[链表加法] LeetCode.2
    无重复字符的最长子串[双指针+哈希表] LeetCode.3
    Rikka with Game[技巧]----2019 杭电多校第九场:1005
    度度熊与排列[搜索+剪枝]----2019 年百度之星·程序设计大赛
    度度熊与数字[公因数]----2019 年百度之星·程序设计大赛
    最大层内元素和----leetcode周赛150_1002
    拼写单词[哈希表]----leetcode周赛150_1001
    Seq[找规律]----2019 年百度之星·程序设计大赛
    实验三
    实验二
  • 原文地址:https://www.cnblogs.com/captain1/p/9637056.html
Copyright © 2020-2023  润新知