您的位置:首页 > 运维架构

poj 2976 Dropping tests (01分数规划)

2017-01-14 15:26 483 查看
Dropping tests

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 10428 Accepted: 3629
Description

In a certain course, you take n tests. If you get ai out of bi questions correct on test i, your cumulative average is defined to be


.
Given your test scores and a positive integer k, determine how high you can make your cumulative average if you are allowed to drop any k of your test scores.

Suppose you take 3 tests with scores of 5/5, 0/1, and 2/6. Without dropping any tests, your cumulative average is 

. However, if you drop the third test, your cumulative average becomes 

.

Input

The input test file will contain multiple test cases, each containing exactly three lines. The first line contains two integers, 1 ≤ n ≤ 1000 and 0 ≤ k < n. The second line contains n integers indicating ai for
all i. The third line contains n positive integers indicating bi for all i. It is guaranteed that 0 ≤ ai ≤ bi ≤ 1, 000, 000, 000. The end-of-file is marked by a test case
with n = k = 0 and should not be processed.

Output

For each test case, write a single line with the highest cumulative average possible after dropping k of the given test scores. The average should be rounded to the nearest integer.

Sample Input
3 1
5 0 2
5 1 6
4 2
1 2 7 9
5 6 7 9
0 0

Sample Output
83
100

Hint

To avoid ambiguities due to rounding errors, the judge tests have been constructed so that all answers are at least 0.001 away from a decision boundary (i.e., you can assume that the average is never 83.4997).

Source

Stanford Local 2005
[Submit]   [Go Back]   [Status]  
[Discuss]

题目大意:给出n个分数ai/bi,可以扔到任意k个

使sigma(ai)/sigma(bi)*100的值最大

题解:01分数规划

01分数规划问题:所谓的01分数规划问题就是指这样的一类问题,给定两个数组,a[i]表示选取i的收益,b[i]表示选取i的代价。如果选取i,定义x[i]=1否则x[i]=0。每一个物品只有选或者不选两种方案,求一个选择方案使得R=sigma(a[i]*x[i])/sigma(b[i]*x[i])取得最值,即所有选择物品的总收益/总代价的值最大或是最小。

令R=sigma(a[i]*x[i])/sigma(b[i]*x[i])

定义一个函数F(L):=sigma(a[i]*x[i])-L*sigma(b[i]*x[i]),显然这只是对目标式的一个简单的变形。分离参数,得到F(L):=sigma((a[i]-L*b[i])*x[i])。这时我们就会发现,如果L已知的话,a[i]-L*b[i]就是已知的,当然x[i]是未知的。记d[i]=a[i]-L*b[i],那么F(L):=sigma(d[i]*x[i])。

我们来分析一下这个函数,它与目标式的关系非常的密切,L就是目标式中的R,最大化R也就是最大化L。

F的值是由两个变量共同决定的,即方案X和参数L。对于一个确定的参数L来说,方案的不同会导致对应的F值的不同,那么这些东西对我们有什么用呢?

假设我们已知在存在一个方案X使得F(L)>0,这能够证明什么?

F(L)=sigma(a[i]*x[i])-L*sigma(b[i]*x[i])>0即sigma(a[i]*x[i])/sigma(b[i]*x[i])>L也就是说,如果一个方案使得F(L)>0说明了这组方案可以得到一个比现在的L更优的一个L,既然有一个更优的解,那么为什么不用呢?

显然,d数组是随着L的增大而单调减的。也就是说,存在一个临界的L使得不存在一种方案,能够使F(L)>0. 我们猜想,这个时候的L就是我们要求的最优解。之后更大的L值则会造成无论任何一种方案,都会使F(L)<0.类似于上面的那个变形,我们知道,F(L)<0是没有意义的,因为这时候的L是不能够被取得的。当F(L)=0使,对应方案的R值恰好等于此时的L值。

 综上,函数F(L)有这样的一个性质:在前一段L中可以找到一组对应的X使得F(L)>0,这就提供了一种证据,即有一个比现在的L更优的解,而在某个L值使,存在一组解使得F(L)=0,且其他的F(L)<0,这时的L无法继续增大,即这个L就是我们期望的最优解,之后的L会使得无论哪种方案都会造成F(L)<0.而我们已经知道,F(L)<0是没有任何意义的,因为此时的L值根本取不到。

根据如上所述,我们可以二分答案然后判定,来求解01分数规划问题。

对于这道题来说就是在简单01分数规划的基础上加了数量限制(n-k)

设c[i]=a[i]-L*b[i],那么我们将c从大到小排序,然后取前(n-k)大,判断和与0的关系即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 10003
#define eps 1e-6
using namespace std;
int n,m;
double a
,b
,c
;
int cmp(double x,double y)
{
return x>y;
}
bool check(double x)
{
for (int i=1;i<=n;i++) c[i]=a[i]-x*b[i];
sort(c+1,c+n+1,cmp);
double sum=0;
for (int i=1;i<=m;i++) sum+=c[i];
return sum>=0;
}
int main()
{
freopen("a.in","r",stdin);
while (true){
scanf("%d%d",&n,&m);
m=n-m;
if (!n&&!m) break;
for (int i=1;i<=n;i++) scanf("%lf",&a[i]);
for (int i=1;i<=n;i++) scanf("%lf",&b[i]);
double l=0; double r=0; double ans=0;
for (int i=1;i<=n;i++) r=max(r,a[i]/b[i]);
while (r-l>=eps) {
double mid=(l+r)/2;
if (check(mid)) ans=max(ans,mid),l=mid+eps;
else r=mid-eps;
}
//cout<<ans<<endl;
printf("%.0lf\n",ans*100);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: