zoukankan      html  css  js  c++  java
  • 【BZOJ4753】最佳团体(分数规划,动态规划)

    【BZOJ4753】最佳团体(分数规划,动态规划)

    题面

    BZOJ

    Description

    JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号。方便起见,JYY的编号是0号。每个候选人都由一位
    编号比他小的候选人Ri推荐。如果Ri=0则说明这个候选人是JYY自己看上的。为了保证团队的和谐,JYY需要保证,
    如果招募了候选人i,那么候选人Ri"也一定需要在团队中。当然了,JYY自己总是在团队里的。每一个候选人都有
    一个战斗值Pi",也有一个招募费用Si"。JYY希望招募K个候选人(JYY自己不算),组成一个性价比最高的团队。
    也就是,这K个被JYY选择的候选人的总战斗值与总招募总费用的比值最大。

    Input

    输入一行包含两个正整数K和N。
    接下来N行,其中第i行包含3个整数Si,Pi,Ri表示候选人i的招募费用,战斗值和推荐人编号。
    对于100%的数据满足1≤K≤N≤2500,0<"Si,Pi"≤10^4,0≤Ri<i

    Output

    输出一行一个实数,表示最佳比值。答案保留三位小数。

    Sample Input

    1 2

    1000 1 0

    1 1000 1

    Sample Output

    0.001

    题解

    典型的分数规划
    二分答案后将点权转换为(P-mid·S)
    然后做一个树上背包就行了

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define RG register
    #define MAX 3000
    inline int read()
    {
        RG int x=0,t=1;RG char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    int n,K,P[MAX],S[MAX],fa[MAX];
    struct Line{int v,next;}e[MAX];
    int h[MAX],cnt=1,size[MAX];
    inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
    double v[MAX],f[MAX][MAX],tmp[MAX];
    void Merge(int x,int y)
    {
    	for(int i=0;i<=K+1;++i)tmp[i]=-1e18;
    	for(int i=1;i<=size[x];++i)
    		for(int j=1;j<=min(K+1-i,size[y]);++j)
    			tmp[i+j]=max(f[x][i]+f[y][j],tmp[i+j]);
    	for(int i=0;i<=K+1;++i)f[x][i]=max(f[x][i],tmp[i]);
    }
    void dfs(int u)
    {
    	f[u][1]=v[u];size[u]=1;
    	for(int i=h[u];i;i=e[i].next)
    		dfs(e[i].v),Merge(u,e[i].v),size[u]+=size[e[i].v];
    }
    bool check(double mid)
    {
    	//v[0]=-1e18;
    	for(int i=0;i<=n;++i)
    		for(int j=0;j<=K+1;++j)
    			f[i][j]=-1e18;
    	memset(size,0,sizeof(size));
    	for(int i=1;i<=n;++i)v[i]=P[i]-mid*S[i];
    	dfs(0);
    	return f[0][K+1]>=0;
    }
    int main()
    {
    	K=read();n=read();
    	for(int i=1;i<=n;++i)
    	{
    		S[i]=read();P[i]=read();
    		fa[i]=read();Add(fa[i],i);
    	}
    	double l=0,r=1e6;
    	while(r-l>1e-4)
    	{
    		double mid=(l+r)/2;
    		if(check(mid))l=mid;
    		else r=mid;
    	}
    	printf("%.3lf
    ",l);
    	return 0;
    }
    
    
  • 相关阅读:
    jquery获取当前时间比较日期
    php获取时间计算时间差
    计数查询统计
    jQuery选取所有复选框被选中的值并用Ajax异步提交数据
    在java中实现对access数据库的远程访问
    sublime快捷键
    局部变量和成员变量的区别
    常见的几种数组排序方法
    JVM的内存划分
    Java函数
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9083721.html
Copyright © 2011-2022 走看看