01分数规划

01分数规划,最近是因为牛客网暑假训练赛第五场的A题才发现这个东西…………

其实说白了,就是一条公式的推导,然后推着推着就发现可以用二分去找答案,

就是这样,当然,也可以用Dinkelbach算法,不过我没有学,所以就不说这个了

先给你两个数列s[i],c[i];求去掉k个i后, ∑(s[i])/∑(c[i])的最大值 

  我们定义x[i]选或不选,即求一个选择方案使得R=∑(a[i]*x[i])/∑(b[i]*x[i])取得最值

    设F(L)=∑(a[i]*x[i])-L*∑(b[i]*x[i]);(可以看到L=0时就是目标值R)

        F(L)=∑((a[i]-L*b[i])*x[i]);(这时发现F(L)随着L的增大而减小,因此可以二分找答案)

到这里分析就结束了

这是poj2976Dropping tests 入门题

#include<iostream>
#include <iomanip>
#include<algorithm>
using namespace std;
#define MAX 1005
const double eps=1e-9;
double a[MAX],b[MAX];
double d[MAX];
int n,k;
bool C(double x)
{
    for(int i=0;i<n;i++)
        d[i]=(a[i]-x*b[i]);
        /*for(int i=0;i<n;i++)
            cout<<d[i]<<endl;*/
    double sum=0;
    sort(d,d+n);
    for(int i=k;i<n;i++)
        sum+=d[i];
    return sum>0;
}
int main()
{
   while(cin>>n>>k)
   {
       if(n==0&&k==0)break;
       for(int i=0;i<n;i++)
           cin>>a[i];
        for(int j=0;j<n;j++)
            cin>>b[j];
            double ans=0;
            double mid;
            double lb=0,ub=100.0;
        while(ub-lb>eps)
        {
             mid=(lb+ub)/2;
            if(C(mid))lb=mid;
            else ub=mid;
        }
        printf("%.0f\n",ub*100);
   }
   return 0;
}

还有牛客网的

题目:链接:https://www.nowcoder.com/acm/contest/143/A
来源:牛客网

题目描述

Kanade selected n courses in the university. The academic credit of the i-th course is s[i] and the score of the i-th course is c[i].

At the university where she attended, the final score of her is 

Now she can delete at most k courses and she want to know what the highest final score that can get.

输入描述:

The first line has two positive integers n,k

The second line has n positive integers s[i]

The third line has n positive integers c[i]

输出描述:

Output the highest final score, your answer is correct if and only if the absolute error with the standard answer is no more than 10
-5
示例1

输入

复制
3 1
1 2 3
3 2 1

输出

复制
2.33333333333

说明

Delete the third course and the final score is 
\frac{2*2+3*1}{2+1}=\frac{7}{3}

备注:

1≤ n≤ 105

0≤ k < n

1≤ s[i],c[i] ≤ 10^3
这是代码:
#include<bits/stdc++.h>
using namespace std;
#define MAX 100005
const double eps=1e-9;
double a[MAX],b[MAX],p[MAX];
int n,k;
double lb=0,ub=1000.0;
double mid;
bool C(double x)
{
    memset(p,0,sizeof(p));
    for(int i=0;i<n;i++)
        p[i]=a[i]*b[i]-x*a[i];
    sort(p,p+n);
    double sum=0;
    for(int i=k;i<n;i++)
    {
       sum+=p[i];
    }
    return sum>0;
}
int main()
{
   cin>>n>>k;
   for(int i=0;i<n;i++)
    cin>>a[i];
   for(int j=0;j<n;j++)
    cin>>b[j];
   while(ub-lb>eps)
   {
       mid=(lb+ub)/2;
       if(C(mid))lb=mid;
       else ub=mid;
   }
   cout<<setprecision(11)<<mid<<endl;
   return 0;
}

最后给出学习的链接:https://blog.csdn.net/Hhaile/article/details/8883652

其实还有最优比率生成树问题、最优比率环问题等,这些还要抓紧时间学!

 

 

posted @ 2018-08-05 00:21  better46  阅读(388)  评论(0编辑  收藏  举报