POJ 2976 二分求平均值最大

题意: n个物品有重量w价值v,取出k个使得单位重量价值最大。

思路:

  二分,单位重量价值a = sigama(v) / sigama(w),令左<=右,转移方程有 sigama(v - a*w) >= 0。----1

  对于二分查找单位重量价值a,排序求出最大k个物品使得sigama(v - a*w)最大。

  此时:

    若条件1满足,则显然存在更好的方案,因为至少还有该方案。

    若条件1不满足,则不存在更好的方案:

      反证:现有 sigama(v1 - a1*w1) < 0 即 a1 > sigama(v1)/sigama(w1) 记为方案1,若存在方案2使得sigama(v2)/sigama(w2) = a2 > a1,则有sigama(v2)/sigama(w2) = a2 > a1 > sigama(v1)/sigama(w1) 与计算sigama(v - a*w) >= 0时取最大方案矛盾,故成立

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <utility>
#include <vector>
#include <queue>
#include <map>
#include <set>
#define INF 0x3f3f3f3f

using namespace std;

double a[1005], b[1005], w[1005];
int n, k;

int main()
{
    while(scanf("%d%d", &n, &k) != EOF && n)
    {
        k = n-k;
        for(int i = 0; i < n; i ++)
            scanf("%lf", &a[i]);
        for(int i = 0; i < n; i ++)
            scanf("%lf", &b[i]);
        double l = 0, r = 1;
        while(r-l > 1e-4)
        {
            double mid = (l+r)/2;
            for(int i = 0; i < n; i ++)
                w[i] = a[i]-mid*b[i];
            sort(w, w+n);
            double max = 0;
            for(int i = n-1; i >= n-k; i --)
                max += w[i];
            if(max >= 0)
                l = mid;
            else
                r = mid;
        }
        printf("%.f\n", l*100);
    }
    return 0;
}

其实这题若单纯想很容易想到二分法,不过细想反而可能想歪掉。

对于最优方案v、w、a,有 a>a‘,有sigama(v-a *w) == 0 且 永远保证 sigama(v - a‘ *w) >= 0,不过并不能保证sigama(v - a‘ *w)最大。

也就是说 sigama(v - a‘ *w) >= 0条件和最优方案是等价的。

时间: 2024-10-17 15:07:28

POJ 2976 二分求平均值最大的相关文章

poj 2976(二分搜索+最大化平均值)

传送门:Problem 2976 参考资料: [1]:http://www.hankcs.com/program/cpp/poj-2976-dropping-tests-problem-solution-challenge-programming-contest.html [2]:http://www.cnblogs.com/demian/p/7498407.html 有感而发: 太晚了,身心疲惫,如果明天有空的话,再写上自己对于此题的理解吧,真是个充实愉快的一天啊. 对了,今天是我们学校70周

POJ 2976 3111(二分-最大化平均值)

POJ 2976 题意 给n组数据ai,bi,定义累计平均值为: 现给出一个整数k,要求从这n个数中去掉k个数后,最大累计平均值能有多大?(四舍五入到整数) 思路 取n?k个数,使得累计平均值最大. 定义C(x)表示能否取得n?k个数,使得累计平均值≥x.然后二分搜索最大的x. 可以这样判断可行性: 只需要从大到小选取n?k个(100?ai?x?bi)并求和sum,根据sum≥0来判断(上述的S表示n?k个元素下标的集合) #include <iostream> #include <al

POJ 3233-Matrix Power Series(矩阵快速幂+二分求矩阵和)

Matrix Power Series Time Limit:3000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 3233 Appoint description:  System Crawler  (2015-02-28) Description Given a n × n matrix A and a positive integer k, find the

POJ 3525 二分+半平面交

Most Distant Point from the Sea Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3812   Accepted: 1779   Special Judge Description The main land of Japan called Honshu is an island surrounded by the sea. In such an island, it is natural t

POJ - 2976 Dropping tests &amp;&amp; 0/1 分数规划

POJ - 2976 Dropping tests 你有 \(n\) 次考试成绩, 定义考试平均成绩为 \[\frac{\sum_{i = 1}^{n} a_{i}}{\sum_{i = 1}^{n} b_{i}}\] 你可以考虑放弃 \(K\) 次成绩, 求最大平均成绩 * 100 小插曲: 被精度卡成喜羊羊 0/1分数规划\(from\)人生导师 Solution 01分数规划(不是很)裸题, 在每次 \(check\) 时, 选取较大的 \(num - K + 1\) 次即可 Code #

求平均值接口与实现该接口的类

求平均值接口与实现该接口的类,声明一个Average接口,其中约定求平均值的方法,声明多个类实现Average接口,分别给出求平均值的方法实现,例如,在第一组数值中,算法一 全部数值相加后求平均值,算法二,去掉一个最高分和一个最低分,再将总分求平均,算法三,求加权平均分的值. 1,在主函数中声明了三个类,第一个类实现全部算法相加后求平均值. 2,第二个类实现去掉一个最高分和一个最低分之后求平均值. 3.第三个类实现求加权平均分的值. 4,程序运行后产生的结果是32.75,9.25,6.75 5,

二分求幂,快速求解a的b次幂

一个引子 如何求得a的b次幂呢,那还不简单,一个for循环就可以实现! void main(void) { int a, b; int ans = 1; cin >> a >> b; for (int i = 1; i <= b; i++) { ans *= a; } cout << ans; } 那么如何快速的求得a的b次幂呢?上面的代码还可以优化吗? 当然是ok的!下面就介绍一种方法-二分求幂. 二分求幂 所谓二分求幂,即是将b次幂用二进制表示,当二进制位k位

HDU - 1588 Gauss Fibonacci (矩阵快速幂+二分求等比数列和)

Description Without expecting, Angel replied quickly.She says: "I'v heard that you'r a very clever boy. So if you wanna me be your GF, you should solve the problem called GF~. " How good an opportunity that Gardon can not give up! The "Prob

生成指定范围的一组随机数并求平均值

Math.random()是令系统随机选取大于等于 0.0 且小于 1.0 的伪随机 double 值,是Java语言常用代码. 随机数生成20~90之间的数值,并求平均数: public class Random01 { public static void main(String[] args) { int len = 5; int sum = 0; int[] arr = new int[len]; for (int i = 0; i < len; i++) { arr[i] = (int