BZOJ 4753 二分+树形DP
2024-10-20 08:53:06
思路:
先二分答案
f[x][j]表示在x的子树里选j个点
f[x][j+k]=max(f[x][j+k],f[x][j]+f[v[i]][k]);
初始化
x!=0 -> f[x][1]=p[x]-s[x]*mid
x=0 -> f[x][0]=0
类似4033的那样转移 看似O(n^3)实际O(n^2)
加一个二分 复杂度O(能过)
//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=;
int n,K,s[N],p[N],r[N],first[N],next[N],v[N],tot,size[N];
double f[N][N],mid;
void add(int x,int y){v[tot]=y,next[tot]=first[x],first[x]=tot++;}
void dfs(int x){
if(x){size[x]=;f[x][]=p[x]-s[x]*mid;}
else size[]=,f[][]=;
for(int i=first[x];~i;i=next[i]){
dfs(v[i]);
for(int j=size[x];j>=;j--){
for(int k=size[v[i]];k>=;k--){
f[x][j+k]=max(f[x][j+k],f[x][j]+f[v[i]][k]);
}
}
size[x]+=size[v[i]];
}
}
int main(){
memset(first,-,sizeof(first));
scanf("%d%d",&K,&n);
for(int i=;i<=n;i++){
scanf("%d%d%d",&s[i],&p[i],&r[i]);
add(r[i],i);
}
double l=,r=0x3f3f3f;
while(r-l>1e-){
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
f[i][j]=-0x3f3f3f;
mid=(l+r)/;
dfs();
if(f[][K]>)l=mid;
else r=mid;
}
printf("%.3lf\n",l);
}
最新文章
- 批量下载网站图片的Python实用小工具
- C#枚举中的位运算权限分配浅谈
- node.js Websocket实现扫码二维码登录---GoEasy
- Redis的发布订阅
- TCL_事务控制语言
- java EE 学习
- Eclipse4.3正式版已发布
- C++-传值与传引用的差别
- webstorm激活破解码+++使用技巧
- Photoshop 样式的角度/高度选择器控件
- 不允许用(a+b)/2这种方式求两个数的均值;如下程序在Linux和32位集成开发环境中运行
- 远程过程调用发展历程 WebAPI GRPC Hprose
- array_filter()函数
- sql server选取第m行到第n行的元组
- Linux ifconfig 命令
- Spark2.1.0模型设计与基本架构(上)
- phpstorm 配置 webpack @ 别名跳转
- IE盒模型与W3C盒模型区别
- OpenCV_基于局部自适应阈值的图像二值化
- 删除数据库的数据后让id从1开始算