[poj2976]Dropping tests(01分数规划,转化为二分解决或Dinkelbach算法)

题意:有n场考试,给出每场答对的题数a和这场一共有几道题b,求去掉k场考试后,公式.的最大值

解题关键:01分数规划,double类型二分的写法(poj崩溃,未提交)

或者r-l<=1e-3(右边是精度)

为什么v-xw>=0?(v/x>=x?)

ans要求的是最大值,我们定义:c(x)可以选择使得单位重量的价值>=x,最大值一定满足此函数,此函数关于x单调递减,可以求得一个最大值。求得的x的最大值即是ans。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cmath>
#define maxn 1006
#define eps 1e-8
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
int n,k;
double ans;
struct node{
    double a,b;
}num[maxn];
bool cmp(const node &x,const node &y){
    return x.a-x.b*ans>=y.a-y.b*ans;
}
bool check(double x){
    ans=x;
    sort(num+1,num+n+1,cmp);
    double sum=0;
    for(int i=1;i<=n-k;i++) sum+=num[i].a-x*num[i].b;
    return sum>=-eps;
}

double erfen(double l,double r){
    while(r-l>eps){//for(int i=1;i<=100;i++)
        double mid=(l+r)/2;
        if(check(mid)) l=mid;
        else r=mid;
    }
    return r;
}

int main(){
    while(scanf("%d%d",&n,&k)!=EOF&&(n||k)){
        for(int i=1;i<=n;i++) scanf("%lf",&num[i].a);
        for(int i=1;i<=n;i++) scanf("%lf",&num[i].b);
        double ans=erfen(0,1.0*inf);
        printf("%.0lf
",100*ans);//必须四舍五入
        //printf("%d
",(int)(100*ans+0.5));
    }
    return 0;
}

 2、Dinkelbach算法(原理上比二分更快,因为利用了当前直线所对应的解)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cmath>
#define eps 1e-8
using namespace std;
typedef long long ll;
double a[1010],b[1010];

struct node{
    double num;
    int ord;
}d[1010];

bool cmp(node a,node b){
    return a.num>b.num;
}

int main(){
    int n,k;
    while(scanf("%d%d",&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.0,ans;
        while(1){
            ans=l;
            for(int i=0;i<n;i++){
                d[i].num=a[i]-ans*b[i];
                d[i].ord=i;
            }
            sort(d,d+n,cmp);
            double p=0.0,q=0.0;
            for(int i=0;i<n-k;i++){
                p+=a[d[i].ord];
                q+=b[d[i].ord];
            }
            l=p/q;
            if(fabs(ans-l)<eps)
                break;
        }
        if(ans>1)ans=1;
        if(ans<0)ans=0;
        printf("%.0f
",100*ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/elpsycongroo/p/10353324.html