zoukankan      html  css  js  c++  java
  • BZOJ4753: [Jsoi2016]最佳团体

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 844  Solved: 318
    [Submit][Status][Discuss]

    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

    HINT

    2017.9.12新加数据一组 By GXZlegend

    Source

    应该是比较裸的题目
    01分数规划+树形依赖背包。
    01分数规划的话按照套路二分检验,注意设置好精度
    树形依赖背包注意在枚举的时候上限应该在枚举之后更改否则会被卡成$O(N^3log ans)$
     
     
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int MAXN=1e6+10,INF=1e4+10;
    inline char nc()
    {
        static char buf[MAXN],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++;
    }
    inline int read()
    {
        char c=nc();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=nc();}
        return x*f;
    }
    int N,K;
    int S[MAXN],P[MAXN],R[MAXN];
    struct node
    {
        int u,v,nxt;
    }edge[MAXN];
    int head[MAXN];
    int num=1;
    inline void AddEdge(int x,int y)
    {
        edge[num].u=x;
        edge[num].v=y;
        edge[num].nxt=head[x];
        head[x]=num++;
    }
    double dp[2501][2501],/*i处,选了j个*/siz[MAXN],w[MAXN];
    void find(int now)
    {
        siz[now]=1;
        for(int i=head[now];i!=-1;i=edge[i].nxt)
            find(edge[i].v),siz[now]+=siz[edge[i].v];
    }
    void dfs(int now)
    {
        int tot=0,b=0;
        if(now) dp[now][1]=w[now],tot=1,b++;
        else dp[now][0]=0;
        for(int i=head[now];i!=-1;i=edge[i].nxt)
        {
            dfs(edge[i].v);
            for(int j=tot;j>=b;j--)//背包容量 
                for(int k=1;k<=siz[edge[i].v];k++)
                    dp[now][j+k]=max(dp[now][j+k],dp[now][j]+dp[edge[i].v][k]);
            tot+=siz[edge[i].v];//必须在后面加 
        }
    }
    bool check(double val)
    {
        memset(dp,0xc2,sizeof(dp));
        for(int i=1;i<=N;i++) w[i]=P[i]-val*S[i];
        dfs(0);
        return dp[0][K]>=0;
    }
    int main()
    {
        #ifdef WIN32
        freopen("a.in","r",stdin);
        #else 
        #endif
        memset(head,-1,sizeof(head));
        K=read(),N=read();
        for(int i=1;i<=N;i++)
        {
            S[i]=read(),P[i]=read(),R[i]=read();
            AddEdge(R[i],i);
        }
        find(0);
        double l=0,r=INF;
        double ans=0;
        while(r-l>1e-5)
        {
            double mid=(l+r)/2;
            if(check(mid)) l=mid;
            else r=mid;    
        }
        printf("%.3lf",(l+r)/2);
         return 0;
    }
  • 相关阅读:
    golang删除数组某个元素
    golang用通道实现信号量,控制并发个数
    什么是ScaleIO中的forwards rebuild和backwards rebuild?
    SQL Server中的database checkpoint
    如何将thick provision lazy zeroed的VMDK文件转换为thick provision eager zeroed?
    LoadTestAgentResultsLateException in VS2010
    SQL Server Instance无法启动了, 因为TempDB所在的分区没有了, 怎么办?
    VMware vCenter中, 如何辩认虚机上Raw Device Mapping过了的一块物理磁盘?
    SQL Server AlwaysOn Setup Step-By-Step Guide
    TPC-E在populate测试Database时需要注意的一些事项
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/8456201.html
Copyright © 2011-2022 走看看