• [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;
    }
  • 相关阅读:
    PatentTips
    PatentTips
    PatentTips
    Xvisor ARM32 启动分析
    PatentTips
    PatentTips
    PatentTips
    PatentTips
    PatentTips
    PatentTips
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/10353324.html
Copyright © 2020-2023  润新知