• POJ 3111 K Best 贪心 二分


      题目链接: http://poj.org/problem?id=3111

      题目描述: 在N个物品中让你选出K个, 使得平均价值最大

      解题思路: 这是我错的代码......一会儿回来改啊......一会儿回来可能会很沮丧

      ---------*----------*----------*----------

          我把错的代码删了, 不行看不下去, 确实很沮丧.......我对自己很失望

          这题有毒........二分会超时, 我一直以为for i 1 to 100 这种方式会比 high - low > le-8 这种要优越呢, 其实并没有......因为前一种可能会超时的啊.........要是这道题卡常那不就GG了, 事实证明, 这道题是真的卡常, 讨论区里有好多都说这题有毒........我最后试试i == 50 时候不T, 而其他的时候都超时.......这不就是很伤的吗......

          下面说说这道题的做法, 我们最大化平均值的时候首先想到的就是二分, 我们设G(x) 为单位的重量不小于X, 我们的目标就是要找到满足条件的最大的X, 也就是说我们的OK函数就要判断是否能够找到一个大小为K的集合S, 使得单位重量的价值大于等于X, 我们将当时变形转化为vi - x*wi >= 0  对于 所有的i 属于集合S, 这时我们对于一个整体值vi-x*wi的值的 排序, 贪心的选取前K个, 这样OK函数就写好了, 剩下问题就简单了

      代码: 

    //#include <iostream>
    //#include <cstdio>
    //#include <string>
    //#include <vector>
    //#include <cstring>
    //#include <iterator>
    //#include <cmath>
    //#include <algorithm>
    //#include <stack>
    //#include <deque>
    //#include <map>
    //#include <set>
    //#define lson l, m, rt<<1
    //#define rson m+1, r, rt<<1|1
    //#define mem0(a) memset(a,0,sizeof(a))
    //#define sca(x) scanf("%d",&x)
    //#define de printf("=======
    ")
    //typedef long long ll;
    //using namespace std;
    //
    //const double INF = 20000000.0;
    //const int maxn = 1e5+10;
    //int n, k;
    //struct node {
    //    double v;
    //    int index;
    //    bool operator < (const node & rhs) const {
    //        return v > rhs.v;
    //    }
    //}y[maxn];
    //double v[maxn], w[maxn];
    //
    //bool ok( double x ) {
    //    for( int i = 0; i < n; i++ ) {
    //        y[i].v = v[i] - x*w[i];
    //        y[i].index = i+1;
    //    }
    //    double sum = 0;
    //    sort(y, y+n);
    //    for( int i = 0; i < k; i++ ) {
    //        sum += y[i].v;
    //    }
    //    return sum >= 0;
    //}
    //
    //void solve() {
    //    double low = 0;
    //    double high = INF;
    //    for( int i = 0; i < 100; i++ ) {
    //        double m = (low + high) * 0.5;
    //        if( ok(m) ) {
    //            low = m;
    //        }
    //        else {
    //            high = m;
    //        }
    //    }
    //    for( int i = 0; i < k; i++ ) {
    //        if( i == 0 ) printf( "%d", y[i].index );
    //        else printf( " %d", y[i].index );
    //    }
    //    printf( "
    " );
    //}
    //
    //int main() {
    //    while( scanf( "%d%d", &n, &k ) == 2 ) {
    //        for( int i = 0; i < n; i++ ) {
    //            scanf( "%lf%lf", v+i, w+i );
    //        }
    //        solve();
    //    }
    //    return 0;
    //}
    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cstring>
    #include <iterator>
    #include <cmath>
    #include <algorithm>
    #include <stack>
    #include <deque>
    #include <map>
    #include <set>
    #define lson l, m, rt<<1
    #define rson m+1, r, rt<<1|1
    #define mem0(a) memset(a,0,sizeof(a))
    #define sca(x) scanf("%d",&x)
    #define de printf("=======
    ")
    typedef long long ll;
    using namespace std;
    
    const double INF = 20000000.0;
    const int maxn = 1e5+10;
    int n, k;
    struct node {
        double v;
        int index;
    }y[maxn];
    double v[maxn], w[maxn];
    
    int cmp( node n1, node n2 ) {
        return n1.v > n2.v;
    }
    
    bool ok( double x ) {
        for( int i = 0; i < n; i++ ) {
            y[i].v = v[i] - x*w[i];
            y[i].index = i+1;
        }
        double sum = 0;
        sort(y, y+n, cmp);
        for( int i = 0; i < k; i++ ) {
            sum += y[i].v;
        }
        return sum >= 0;
    }
    
    void solve() {
        double low = 0;
        double high = INF;
        for( int i = 0; i < 50; i++ ) {
    //    while( high - low > 1e-8 ) {
            double m = (low + high) * 0.5;
            if( ok(m) ) {
                low = m;
            }
            else {
                high = m;
            }
        }
    }
    
    int main() {
        while( scanf( "%d%d", &n, &k ) == 2 ) {
            for( int i = 0; i < n; i++ ) {
                scanf( "%lf%lf", v+i, w+i );
            }
            solve();
            for( int i = 0; i < k; i++ ) {
                if( i == 0 ) printf( "%d", y[i].index );
                else printf( " %d", y[i].index );
            }
            printf( "
    " );
        }
        return 0;
    }
    View Code

      思考: 这个题是二分, 自己的代码是不是又写搓了? 哎, 二分专题就先到这里吧, 自己对于二分的总结就是: 将要求的那个值设出来, 再根据已知条件判断我们这个设出来的值是不是符合条件, 二分的不断得去逼近答案......这就是我做了这些二分题对于二分的一些思考, 我自己也会逐渐地去反思, 自己到底欠缺在哪里, 然后进步, 开下个专题然后去打比赛

  • 相关阅读:
    logback
    GC
    常用JVM配置参数
    JVM
    linux
    简单的webService 实例
    [转载]Java 工程师成神之路
    ActiveMQ 在mac 上的安装与运行
    subline3 + emmet 加快前端开发效率
    Spring WebMVC 4.1.4返回json时导致的 406(Not Acceptable)
  • 原文地址:https://www.cnblogs.com/FriskyPuppy/p/7488040.html
Copyright © 2020-2023  润新知