zoukankan      html  css  js  c++  java
  • [洛谷P4322][题解][JSOI2016]最佳团体

    0.???

    似乎又咕咕咕了好久呢……开了学时间少了(绝不是因为我懒哦)
    又刷到了一个有趣的新算法(or新解法?),特此写一写~

    1.概述

    给出一棵树和每个点的(S_i,P_i),只能从根节点向下连续选点,求(max{frac{sum{P_i}}{sum{S_i}}})

    2.解法

    运用到了一种叫做分数规划的解法(虽然听起来很高端其实简单得不能再简单系列)。首先,我们发现答案中的比值太难看了,去除!于是就变成了:(max{sum{(P_i-ans imes S_i)}})。暂且将求和号里面的东西记作(val_i),然后根据(ans)的不同答案也会有不同的取值(当前答案小了还是大了会体现在(sum{val_i}ge 0)(<0),可以自己推一下),这启发我们二分答案
    总结一下:
    1.将答案变换形式,更易于求解;
    2.二分答案+判断。
    之后再往二分里面套一个普通的(DP),设(f[i][j])(i)子树中选(j)个点的最大答案,转移就是依次枚举每个儿子选的个数。

    3.代码

    缺省源在我的博客

    #define N 2510
    int k,n,siz[N];
    double val[N],f[N][N],s[N],p[N];
    struct Edge {
    	int to,nxt;
    }e[N<<1];
    int head[N],cnt;
    inline void ade(int u,int v){
    	e[++cnt].to=v;
    	e[cnt].nxt=head[u];
    	head[u]=cnt;
    }
    void DFS(int now){
    	f[now][1]=val[now],siz[now]=1;
    	for(rg int i=head[now];i;i=e[i].nxt){
    		int v=e[i].to;
    		DFS(v);
    		siz[now]+=siz[v];
    		for(rg int j=min(siz[now],k+1);j;j--){
    			for(rg int l=0;l<=min(siz[now],j-1);l++){
    				f[now][j]=max(f[now][j],f[v][l]+f[now][j-l]);
    			}
    		}
    	}
    }
    bool Check(double mid){
    	for(rg int i=1;i<=n;i++){
    		val[i]=p[i]-mid*s[i];
    	}
    	for(rg int i=0;i<=n;i++){
    		for(rg int j=1;j<=k+1;j++)f[i][j]=-INF;
    	}
    	DFS(0);
    	return f[0][k+1]>=0;
    }
    int main(){
    	Read(k),Read(n);
    	for(rg int i=1;i<=n;i++){
    		int rr;
    		scanf("%lf%lf%d",&s[i],&p[i],&rr);
    		ade(rr,i);
    	}
    	double l=0.0,r=10000.0,mid;
    	while(r-l>eps){
    		mid=(l+r)/2;
    		if(Check(mid))l=mid;
    		else r=mid;
    	}
    	printf("%.3lf
    ",l);
    	return 0;
    }
    

    4.完结撒花~

  • 相关阅读:
    PowerGhost
    watchdogs感染性挖矿病毒
    XorDDoS木马
    Gates(盖茨)木马
    seasame病毒
    zabbix监控之邮件报警通知
    ubuntu18.04 heirloom-mailx 通过外部SMTP服务器发送邮件
    linux小常识
    zabbix基本概念
    Zabbix图表中文乱码
  • 原文地址:https://www.cnblogs.com/juruoajh/p/13616239.html
Copyright © 2011-2022 走看看