您的位置:首页 > Web前端 > JavaScript

BZOJ 4753: [Jsoi2016]最佳团体

2017-09-26 21:16 477 查看
这种题一看就知道是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
; int len,fir
;
void ins(int x,int y){
a[++len]=(edge){y,fir[x]},fir[x]=len;
}
int s
,p
,m,n,sz
; double d
,f

,G
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: