zoukankan      html  css  js  c++  java
  • wyh的物品(二分)

    题目描述 

    wyh学长现在手里有n个物品,这n个物品的重量和价值都告诉你,然后现在让你从中选取k个,问你在所有可能选取的方案中,最大的单位价值为多少(单位价值为选取的k个物品的总价值和总重量的比值)

    输入描述:

    输入第一行一个整数T(1<=T<=10)
    接下来有T组测试数据,对于每组测试数据,第一行输入两个数n和k(1<=k<=n<=100000)
    接下来有n行,每行两个是a和b,代表这个物品的重量和价值

    输出描述:

    对于每组测试数据,输出对应答案,结果保留两位小数
    示例1

    输入

    1
    3 2
    2 2
    5 3
    2 1

    输出

    0.75

    说明

    对于样例来说,我们选择第一个物品和第三个物品,达到最优目的

    思路

    前提我们要知道的一个公式:

    物品价值(v) = 单位价值*物品重量(w)
    
    • 1
    • 2

    对于任意的单位价值m,我们都可以发现: 
    1、对于任意的一个物品,物品实际价值与对于任意单位价值的关系只有三种情况:

    1、x = 物品实际价值(v) -  (任意单位价值(mid)*物品重量(w)) == 0;
    这说明:任意单位价值(mid)==实际单位价值。
    2、x = 物品实际价值(v) -  (任意单位价值(mid)*物品重量(w)) > 0;
    这说明:任意单位价值(mid)<实际单位价值。
    3、x = 物品实际价值(v) -  (任意单位价值(mid)*物品重量(w)) < 0;
    这说明:任意单位价值(mid)>实际单位价值。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这里对应着核心代码:s[i] = v[i] - mid*w[i];

     2、我们将所有这些实际价值与单位价值之差分别存储到一个数组当中,为了保证任意单位价值最大,我们取前k大的差值(x)。 

    这里不太好想,我们换一个思路去思考,x值越大,就说明mid值越小,就说明还有比mid更大实际单位价值的值需要我们去找,我们的目的就是要找到更大的mid值呀。 
    这里对应着核心代码:sort(s,s+n,cmp);

    3、我们把选择出的前k个差值相加,得到前k个差值最大的物品实际价值与物品对于任意单位价值(n)所求得的物品相对价值之差的之和(ss)。 
    这个值有两种情况

    ss>=0 //任意的单位价值n取小了,导致实际价值还有剩余,还有更大的n。
    ss<0  //任意的单位价值n取大了,导致实际价值都不可能满足由这个单位价值算出来的总价值。

    AC:代码

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    const int maxn = (int)1e5+5; 
    int w[maxn],v[maxn];
    double s[maxn]; 
    int n,k;
    using namespace std;
    int cmp(double x,double y)
    {
    	return x>y;
    }
    int slove(double mid)
    {
    	double ss = 0;
    	for(int i = 0;i<n;i++)
    	{
    		s[i] = 1.0*v[i] - w[i]*mid;
    	}
    	sort(s,s+n,cmp);
    	for(int i = 0;i<k;i++)
    	{
    		ss += s[i];
    	}
    	if(ss>=0) return 1;
    	else return 0;
    }
    int main()
    {
    	int t;
    	cin>>t;
    	while(t--)
    	{
    		scanf("%d %d",&n,&k);
    		double low = 0,high = 100000,mid;
    		for(int i = 0;i<n;i++)
    		{
    			scanf("%d %d",&w[i],&v[i]);
    		}
    		while(high - low >0.00001)
    		{
    			mid = (low + high)/2.0;
    			if(slove(mid)) low = mid;
    			else high = mid;
    
    		}
    		printf("%.2lf
    ",low);
    	}
    	return 0;
    }


  • 相关阅读:
    (转)dubbo远程调用细节
    (转)Dubbo扩展点实现细节
    (转)dubbo design
    (转) java中try/catch性能和原理
    mybatis入门基础(九)----逆向工程
    客观评价下软件培训机构
    mybatis入门基础(八)-----查询缓存
    mybatis入门基础(七)----延迟加载
    mybatis入门基础(六)----高级映射(一对一,一对多,多对多)
    为什么我不推荐大家去外包公司
  • 原文地址:https://www.cnblogs.com/Nlifea/p/11746052.html
Copyright © 2011-2022 走看看