• bzoj4753


    bzoj4753 树形dp+01分数规划

    这是一个典型的树形背包+01分数规划。看见分数形式最大就应该想到01分数规划。

    于是套用分数规划,每次用树形背包检验。

    首先这是一棵树,不是一个森林,所以我们不用添加虚点。然后可以列出dp方程,具体代码。

    然后每个点如果自己选了,那么父亲也要选,所以更新的时候,除了jyy也就是0号节点,都是从dp[u][1]开始更新,而且初值就是dp[u][0]=0,dp[u][1]=val,因为儿子选了,自己肯定会选,所以不能出现

    dp[u][i]=dp[u][0]+dp[v][i]这种情况。

    每次背包要从大到小枚举,常见技巧。

    然后判断即是dp[0][k]>=0。

    但是又有一个问题:val[0]是什么?如果是0的话,那么不就无法判断了?

    那么我们这么设置一下,当u=0时,j可以枚举到0,因为jyy不算在k里,所以jyy就可以出现dp[0][i]=dp[0][0]+dp[v][i]的情况。但是val[0]还是设置成-inf,这样才可以取到最大值,否则一上来dp[0][1]就是0了。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 2510;
    const double inf = 1e9, eps = 1e-5;
    int n, k;
    int r[N], size[N];
    double ans;
    double dp[N][N], s[N], p[N], val[N];
    vector<int> G[N];
    void dfs(int u)
    {    
        dp[u][0] = 0;
        dp[u][1] = val[u];
        ++size[u]; 
        for(int i = 0; i < G[u].size(); ++i)
        {
            int v = G[u][i];
            dfs(v);
            for(int j = min(size[u], k); j >= (u == 0 ? 0 : 1); --j)
                for(int l = min(size[v], k); l >= 0; --l) if(j + l <= k)
                {
    //                printf("dp[%d][%d]=%.10f dp[%d][%d]=%.10f dp[%d][%d]=%.10f
    ", u, l + j, dp[u][l + j], u, j, dp[u][j], v, l, dp[v][l]);
                    dp[u][l + j] = max(dp[u][l + j], dp[u][j] + dp[v][l]);
                }
            size[u] += size[v];
        }
        
    }
    bool C(double x)
    {
        for(int i = 0; i <= n; ++i) 
        {
            size[i] = 0;
            val[i] = p[i] - s[i] * x;
            for(int j = 0; j <= k; ++j) dp[i][j] = -inf;
        }
        dfs(0);
        return dp[0][k] >= 0;
    }
    int main()
    {
        scanf("%d%d", &k, &n); 
        s[0] = inf; 
        for(int i = 1; i <= n; ++i)
        {
            scanf("%lf%lf%d", &s[i], &p[i], &r[i]);
            G[r[i]].push_back(i);
        }
        double l = 0, r = 1e4 + 1, mid;
        while(r - l > eps)
        {
            mid = (l + r) / 2.0;
            if(C(mid)) l = ans = mid; 
            else r = mid;
        } 
        printf("%.3f
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    自定义ASP.NET MVC Html标签辅助方法
    解决github.com无法访问
    Func<>用法
    Entity Framework 在OrderBy排序中使用字符串
    <input type="file"> 标签详解
    JS实现上传图片的三种方法并实现预览图片功能
    一个关于双目运算符的测试
    堆和栈的区别
    C# 代码笔记_tuple元组
    小程序前后端自定义登录与一键登录兼容demo分享
  • 原文地址:https://www.cnblogs.com/19992147orz/p/6964392.html
Copyright © 2020-2023  润新知