• 【树上背包】P1273 有线电视网


    P1273 有线电视网

    注意最里面那一层循环是在枚举物品:“选1个叶子节点”、“选2个叶子节点”……

    因为最多只能选(cnt)个叶子节点((cnt)为当前子树中的叶子节点个数),一种优化是先统计出这个(cnt),最里面那层循环从1跑到(cnt)(j)两者之间的最小值就可以结束了,都跑到(j)会TLE。

    const int INF = 0x3f3f3f3f;
    const int maxn = 3e3+10;
    
    int dp[maxn][maxn];
    int num = 0;
    int head[maxn];
    int n,m;
    
    struct Edge {
        int next, to;
        int dis;
    }edges[maxn];
    
    void add_edge(int from, int to,int dis) {
        num++;
        edges[num].next = head[from];
        edges[num].to = to;
        edges[num].dis = dis;
        head[from] = num;
    }
    
    int dfs(int u) {
        if (u > n - m) return 1;
        int sum = 0;
        for (int i = head[u]; i; i = edges[i].next) {
            int v = edges[i].to;
            //第一层循环:枚举节点u的每一个儿子,一个儿子代表的子树为一组
            int cnt = dfs(v);
            sum += cnt;
            //这是在数以u为根节点的子树有多少个叶子节点
            for (int j = m; j >= 0; j--) {
                //第二层循环:枚举背包容量
                for (int k = 0; k <= min(cnt,j); k++) {
                    //第三层循环:枚举组内物品:选1个用户,选2个用户,选3个用户...
                    //显然最多只能选不超过j个用户且不超过cnt个用户,即最多选两者中的最小值
                    dp[u][j] = max(dp[u][j], dp[u][j - k] + dp[v][k] - edges[i].dis);
                }
            }
        }
        return sum;
    }
    //dp[i][j]:=在以i为根节点的子树中,选择j个叶子节点时的最大获利
    int main()
    {
        //ios::sync_with_stdio(false);
        //while (scanf("%d%d",&n,&m)!=EOF){
        memset(dp, ~INF, sizeof(dp));
        cin >> n >> m;
        for (int i = 1; i <= n-m; i++) {
            int k; cin >> k;
            for (int j = 1; j <= k; j++) {
                int v; int d;
                cin >> v >> d;
                add_edge(i, v, d);
            }
        }
        for (int i = 1; i <= m; i++) cin >> dp[n - m + i][1];
        for (int i = 1; i <= n; i++) dp[i][0] = 0;
        dfs(1);
        for (int i = m; i >= 1; i--) {
            if (dp[1][i] >= 0) {
                cout << i;
                break;
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    Java——方法的重载
    JS数据类型之String类型
    常用的正则表达式
    关于前端面试遇到的问题值类型和引用类型,1rem等于多少像素
    JS数据类型之Number类型
    常用前端面试题链接
    Wpf 父子容器的关系 ^
    心情 ^
    sharepoint_wf 启动窗口设计,支配给自由域用户 ^
    WPF 单个触发器、多个触发器、多条件触发器 ^
  • 原文地址:https://www.cnblogs.com/streamazure/p/13689094.html
Copyright © 2020-2023  润新知