[POJ 2976] Dropping tests (二分答案)

N门课程,每个课程有一个分数和总分,可以丢掉最多K个课程
问平均分最大是多少
有一个贪心思路就是尽量把平均分低的课程丢掉,但是这样连样例都过不了
而去枚举那些课程要丢掉,是NP困难的。
所以我们可以二分一下答案 ans,有 ΣNi=1aibians
整理后得 ΣNi=1aiansbi0
然后排个序,贪心选取就好了

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std;
typedef pair<int,int> Pii;
typedef long long LL;
typedef unsigned long long ULL;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Pow2(a) a*a
int maxx(int a,int b){return a>b?a:b;}
int minn(int a,int b){return a<b?a:b;}
int abss(int a){return a<0?(-a):a;}

const int maxn=1e3+10;
int N,K;
LL inpt[maxn][2];
LL sque[maxn];

bool judg(int);

int main()
{
    while(~scanf("%d%d", &N, &K)&&N)
    {
        for(int i=1; i<=N; i++) scanf("%d", &inpt[i][0]);
        for(int i=1; i<=N; i++) scanf("%d", &inpt[i][1]);
        int l=0,r=100000;
        while(l<r)
        {
            int mid=(l+r+1)>>1;
            if(judg(mid)) l=mid;
            else r=mid-1;
        }
        double ans=l/1000.0+0.5;
        printf("%d\n", (int)ans);
    }
    return 0;
}

bool judg(int ans)
{
    LL tot=0;
    for(int i=1; i<=N; i++)
    {
        sque[i]=100000*inpt[i][0]-ans*inpt[i][1];
        tot+=sque[i];
    }
    sort(sque+1,sque+1+N);
    if(tot>=0) return 1;
    for(int i=1; i<=K; i++)
    {
        tot-=sque[i];
        if(tot>=0) return 1;
    }
    return 0;
}

你可能感兴趣的:(poj)