bzoj 4753 [Jsoi2016]最佳团体——0/1分数规划

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4753

0/1分数规划裸题。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define db double
using namespace std;
const int N=2505;
const db eps=1e-5,INF=1e8;
int n,k,s[N],p[N],hd[N],xnt,to[N],nxt[N],siz[N];
db ans,l,r,mid,a[N],dp[N][N];
int rdn()
{
    int ret=0;bool fx=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
    while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
    return fx?ret:-ret;
}
void add(int x,int y)
{
    to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;
}
void dfs(int cr)
{
    dp[cr][1]=a[cr]; siz[cr]=1;
    for(int j=2;j<=k;j++) dp[cr][j]=-INF;
    for(int i=hd[cr],v;i;i=nxt[i])
    {
        dfs(v=to[i]);
        for(int j=min(k,siz[cr]+siz[v]);j>=1;j--)
            for(int l=max(1,j-siz[cr]);l<=siz[v]&&l<j;l++)
                dp[cr][j]=max(dp[cr][j],dp[v][l]+dp[cr][j-l]);
        siz[cr]+=siz[v];
    }
}
bool check()
{
    for(int i=1;i<=n;i++)
        a[i]=p[i]-s[i]*mid;
    dfs(0);
    return dp[0][k]>=0;
}
int main()
{
    k=rdn()+1; n=rdn();
    for(int i=1,d;i<=n;i++)
    {
        s[i]=rdn(); p[i]=rdn();
        d=rdn(); add(d,i); r+=p[i];
    }

    for(int i=0;i<=n;i++) dp[i][0]=-INF;
    while(r-l>eps)
    {
        mid=(l+r)/2;
        if(check()) ans=mid,l=mid+eps;
        else r=mid-eps;
    }
    printf("%.3lf\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Narh/p/9707472.html