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;
    }
  • 相关阅读:
    C#数组学习
    关于servlet中要写初始化逻辑应该重载有参还是无参的init
    servlet初识servletConfig
    servlet通过响应头Content-Disposition实现文件下载效果
    response中setCharacterEncoding和setContentType的区别
    通过refresh响应头,定时刷新或隔n秒跳转页面
    通过location响应头实现重定向
    三层交换原理
    什么是CLOS架构?
    Cat8 八类网线是什么?与Cat5、Cat6、Cat7网线的区别?
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/8456201.html
Copyright © 2011-2022 走看看