• 01分数规划初探?!By cellur925


    都要(NOIp)了为啥我还在看这种玄学玩意.....

    (01)分数规划:这是一个问题模型(qwq),一般是在求$$frac{sum_{i=1}^{n} a_ix_i}{sum_{i=1}^{n} b_ix_i}$$

    其中(x_i)(0)(1)

    通俗地讲,也就是给定(n)对整数(a_i)(b_i),从中选出若干对,使选出的数对 的(a_i)之和与(b_i)之和的商最大。

    中间的思维过程就暂时不给出了::>_<::...直接江算法惹(qwq)

    方法:二分最终答案(实数)。当二分的值为(mid),检查(sum_{i=1}^{n}(a_i-mid*b_i)*x_i)的最大值是否非负。往往这里是难点,其他可能都是一些套路化的东西。

    我们看一道题:P4377 [USACO18OPEN]Talent Show。

    因为要求总质量大于等于(W),这就是本题的约束,我们如何在这个条件下最大值,考虑(01)背包。

    细节:背包初值为负无穷。但是题解写的很玄学...这是一个待填坑。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    
    using namespace std;
    const double eps=1e-8;
    
    int n,W;
    int w[500],t[500];
    double f[2000];
    //f[i]表示重量为i的最大价值 
    bool check(double x)
    {
    	for(int i=1;i<=W;i++) f[i]=-1e9;
    	f[0]=0;
    	int lim=f[W];
    	for(int i=1;i<=n;i++)
    		for(int j=W;j>=0;j--)
    			if(f[j]!=lim)
    				f[min(W,j+w[i])]=max(f[min(W,j+w[i])],f[j]+t[i]-1.0*x*w[i]);
    	return f[W]>=0;
    }
    
    int main()
    {
    	scanf("%d%d",&n,&W);
    	for(int i=1;i<=n;i++)
    		scanf("%d%d",&w[i],&t[i]),t[i]*=1000;
    	double l=0,r=1e9;
    	while(l+eps<r)
    	{
    		double mid=(l+r)/2;
    		if(check(mid)) l=mid;
    		else r=mid;
    	}
    	int ans=l;
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    Linux系统_Linux平台“盖茨木马”初步了解
    查杀病毒的NB命令
    rabbitmq 常用的一些命令
    date 修改系统时间
    mkpasswd
    关于haproxy负载均衡的算法整理
    MySQL数据表中内容大小写区分的设置
    查看某个端口的连接数
    rabbitmq
    mysqldump 报导常
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9922588.html
Copyright © 2020-2023  润新知