zoukankan      html  css  js  c++  java
  • [JSOI2016]最佳团体

    输入输出样例

    输入样例#1:

    1 2
    1000 1 0
    1 1000 1

    输出样例#1:

    0.001


    一看到这种最大化比值的问题应该就能想到分数规划吧

    但是好久没写了,这次再推一下加深记忆

    (frac{sum_{i=1}^{n}{p[i]}}{sum_{i=1}^{n}{s[i]}}=k)

    (k*sum_{i=1}^{n}{s[i]}=sum_{i=1}^{n}{p[i]})

    (sum_{i=1}^{n}{p[i]}-k*sum_{i=1}^{n}{s[i]} == 0)

    所以我们就二分这个k

    然后选择每个人的价值就变成了([i]-k*s[i])

    直接树上依赖背包就好辣

    最大化这个值,看看最后(f[1][m])是否大于这个值

    还有就是这题卡常数,我被卡了好几发50

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const int M = 2505 ;
    const double eps = 1e-4 ;
    using namespace std ;
    inline int read() {
        char c = getchar() ; int x = 0 , w = 1 ;
        while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
        while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; }
        return x*w ;
    }
    
    int n , m ;
    double s[M] , p[M] , Ans ;
    int hea[M] , num , size[M] ;
    double f[M][M] , res ;
    struct E { int Nxt , to ; } edge[M << 1] ;
    inline void add_edge(int from , int to) {
        edge[++num].Nxt = hea[from] ;
        edge[num].to = to ;
        hea[from] = num ;
    }
    void Dfs(int u) {
        f[u][1] = p[u] - res * s[u] ; f[u][0] = 0 ; size[u] = 1 ;
        for(int i = hea[u] , v ; i ; i = edge[i].Nxt) {
            v = edge[i].to ;
            Dfs(v) ;
            size[u] += size[v] ;
            for(int j = size[u] ; j >= 0 ; j --)
                for(int k = 0 ; k <= size[v] && k < j ; k ++)
                    f[u][j] = max(f[u][j] , f[u][j - k] + f[v][k]) ;
        }
    }
    inline bool chk(double mid) {
        res = mid ;
        memset(f , -63 , sizeof(f)) ;
        Dfs(1) ;
        return (f[1][m] >= 0) ;
    }
    int main() {
        m = read() + 1 ; n = read() + 1 ;
        for(int i = 2 , x ; i <= n ; i ++) {
            s[i] = read() ; p[i] = read() ; x = read() + 1 ;
            add_edge(x , i) ;
        }
        double l = 0 , r = 1e4 , mid ;
        while(r - l >= eps) {
            mid = (l + r) / 2.0 ;
            if(chk(mid)) l = mid , Ans = mid ;
            else r = mid ;
        }
        printf("%.3lf
    ",Ans) ;
        return 0 ;
    }
    
  • 相关阅读:
    Android Button上的文字自动变成大写,如何解决呢?
    如何在IamgeButton上面添加文字
    C语言之实现函数返回一个数组,以及选择排序,还有折半查找。这是同学的一个作业。。。
    解决android:background背景图片被拉伸问题
    service&thread
    MS SQLServer Update语法和实例
    ztree2.6给菜单增加title提示信息[转]
    UltraEdit-14.10.0.1024版本语法着色配置
    linux下c++动态库的生成及使用
    c++动态库与静态库
  • 原文地址:https://www.cnblogs.com/beretty/p/9703123.html
Copyright © 2011-2022 走看看