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;
    }
    
  • 相关阅读:
    【BZOJ 4581】【Usaco2016 Open】Field Reduction
    【BZOJ 4582】【Usaco2016 Open】Diamond Collector
    【BZOJ 4580】【Usaco2016 Open】248
    【BZOJ 3754】Tree之最小方差树
    【51Nod 1501】【算法马拉松 19D】石头剪刀布威力加强版
    【51Nod 1622】【算法马拉松 19C】集合对
    【51Nod 1616】【算法马拉松 19B】最小集合
    【51Nod 1674】【算法马拉松 19A】区间的价值 V2
    【BZOJ 2541】【Vijos 1366】【CTSC 2000】冰原探险
    【BZOJ 1065】【Vijos 1826】【NOI 2008】奥运物流
  • 原文地址:https://www.cnblogs.com/tqr06/p/11631896.html
Copyright © 2011-2022 走看看