BZOJ 4753: [Jsoi2016]最佳團體

這種題一看就知道是01分數規劃啊233(你也不用去細究,就是二分。。

然後 令d[i]=p[i]-mid*s[i]
接着做個treeDP就好了啊 看看選K個的最大值是否>=0即可

因爲按子樹大小合併的揹包是n^2 所以並不會有問題
當然也可以打樹形依賴揹包
DP這裏就不說了 都很裸

你問我打了哪個? 我當然打簡單一點的直接合並啊233

#include<bits/stdc++.h>
using namespace std;
const int N=2505;
const double eps=1e-5,inf=1e12;
char B[1<<14],*S=B,*T=B;
#define g (S==T&&(T=(S=B)+fread(B,1,1<<14,stdin),S==T)?-1:*S++)
inline int read(){
    int x=0,f=1; char ch=g;
    while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=g;}
    while(ch>='0' && ch<='9'){x=(x<<1)+(x<<3)+ch-'0'; ch=g;}
    return x*f;
}
struct edge{int y,nex;}a[N]; int len,fir[N];
void ins(int x,int y){
    a[++len]=(edge){y,fir[x]},fir[x]=len;
}
int s[N],p[N],m,n,sz[N]; double d[N],f[N][N],G[N];
void dfs(int x){
    sz[x]=1;
    f[x][1]=d[x];
    for(int k=fir[x];k;k=a[k].nex){
        int y=a[k].y; dfs(y);
        for(int i=1;i<=sz[x]+sz[y];++i)G[i]=f[x][i];
        for(int i=1;i<=sz[x];++i) if(f[x][i]>-inf)
            for(int j=1;j<=sz[y];++j) if(f[y][j]>-inf)
                G[i+j]=max(G[i+j],f[x][i]+f[y][j]);
        for(int i=1;i<=sz[x]+sz[y];++i)f[x][i]=G[i];
        sz[x]+=sz[y];
    }
}
int main(){
    m=read(),n=read(); int i,j;
    for(i=1;i<=n;++i){
        s[i]=read(),p[i]=read();
        int x=read(); ins(x,i);
    }
    double l=0,r=1e4,ans; d[0]=0;
    while(r-l>eps){
        double mid=(l+r)/2.0;
        for(i=0;i<=n;++i)for(j=1;j<=m+1;++j)f[i][j]=-inf;
        for(i=1;i<=n;++i)d[i]=(double)p[i]-mid*s[i];
        dfs(0);
        if(f[0][m+1]>eps)l=(ans=mid)+eps;
        else r=mid-eps;
    }
    printf("%.3lf\n",ans);
    return 0;
}
發佈了173 篇原創文章 · 獲贊 203 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章