zoukankan      html  css  js  c++  java
  • 【JSOI2016】最佳团体

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

    一看到比值最大,马上搞分数规划

    [dfrac{sum W_i}{sum C_i}leq x ]

    推出

    [sum W_i leq sum x * C_i ]

    所以

    [sum W_i-x*C_i leq 0 ]

    所以二分答案,在树上跑依赖背包即可

    代码:

    #include<bits/stdc++.h>
    #define eps 1e-5
    #define N 2505
    using namespace std;
    
    int k,n;
    double dp[N][N],d[N];
    
    struct People
    {
    	double s,p;
    	int f;
    }a[N];
    
    struct Edge
    {
    	int next,to;
    }edge[N<<1];
    int cnt=0,head[N];
    
    inline void add_edge(int from,int to)
    {
    	edge[++cnt].next=head[from];
    	edge[cnt].to=to;
    	head[from]=cnt;
    }
    
    int dfn[N],tms,las[N];
    void dfs(int u)
    {
    	dfn[u]=tms++;
    	for(register int i=head[u];i;i=edge[i].next) dfs(edge[i].to);
    	las[dfn[u]]=tms;
    }
    
    template<class T>inline void read(T &res)
    {
    	char c;T flag=1;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    	while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
    }
    
    double check(double mid)
    {
    	for(register int i=1;i<=n;++i)
    		d[dfn[i]]=a[i].p-(a[i].s*mid);
    	for(register int i=1;i<=n+1;++i)
    		for(register int j=0;j<=k+1;++j)
    			dp[i][j]=-1234567890;
    	for(register int i=0;i<=n;++i)
    	{
    		int maxn=min(i,k+1);
    		for(register int j=0;j<=maxn;++j)
    		{
    			if(dp[i][j]+d[i]>dp[i+1][j+1]) dp[i+1][j+1]=dp[i][j]+d[i];
    			if(dp[i][j]>dp[las[i]][j]) dp[las[i]][j]=dp[i][j];
    		}
    	}
    	return dp[n+1][k+1];
    }
    
    int main()
    {
    	read(k);read(n);
    	for(register int i=1;i<=n;++i)
    	{
    		scanf("%lf%lf",&a[i].s,&a[i].p);
    		read(a[i].f);
    		add_edge(a[i].f,i);
    	}
    	dfs(0);
    	double l=0.0,r=10000.0;
    	while(r-l>=eps)
    	{
    		double mid=(l+r)/2.0;
    		if(check(mid)>=eps) l=mid;
    		else r=mid;
    	}
    	printf("%.3lf",l);
    	return 0;
    }
    
  • 相关阅读:
    windows下Yarn安装与使用(两种方法)
    git配置公钥---解决码云出现git@gitee.com: Permission denied (publickey)
    npm使用国内镜像的两种方法
    【LeetCode】33. Search in Rotated Sorted Array (4 solutions)
    【LeetCode】83. Remove Duplicates from Sorted List
    【LeetCode】82. Remove Duplicates from Sorted List II
    【LeetCode】85. Maximal Rectangle
    【LeetCode】84. Largest Rectangle in Histogram
    【LeetCode】87. Scramble String
    【LeetCode】162. Find Peak Element (3 solutions)
  • 原文地址:https://www.cnblogs.com/tqr06/p/11631896.html
Copyright © 2011-2022 走看看