题目大意:给你n对a,b,现在让你删除其中k对,使得剩下的n-k对a,b的Σa/Σb的值最大。(所有的a<=b)
这是我第一次做01分数规划的题,写得可能有点辣鸡。结果可以这样写a·x/b·x,a,b,x为向量,x∈{0,1}。x = 0表示不选否则表示选。易知n个x中有k个0。令p = a·x/b·x 。则有ax - p*bx = 0;定义函数f(p) = max{ax - p*bx}。当且仅当f(p) = 0时有最优解,设*p为最优解。因此我们使用二分法枚举p。但是,问题来了,我们在求f(p)的时候连向量x都不知道,怎么办?先提一下公因式f(*p) = (a - p*b)x。因此我们只需要求出最大的n-k个ai - *p*bi,然后判断f(p)的值,如果f(p) = 0,则有p = *p,此时为最优解;如果f(p) > 0 那么p < a·x/b·x
说明此时的p不是最优解,取小了,同理,如果f(p)<0则说明p取大了。
//使用scanf的时候此题推荐用c++编译器,不然WA
#include<cstdio>
#include<algorithm>
#include<cstring>
#define MAXN 1005
#define eps 0.00000001
using namespace std;
double a[MAXN],b[MAXN];
int n,k;
int main()
{
while(scanf("%d%d",&n,&k) != EOF&&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;
double R = 1.0;
double temp[MAXN];
double mid;
while(R-L > eps)
{
mid = (L+R)*1.0/2;
for(int i = 0; i < n; i++)
temp[i] = a[i] - mid*b[i];
sort(temp,temp+n);
double sum = 0;
for(int i = k; i < n; i++)
sum += temp[i];
if(sum > 0)//貌似要写成if(sum > 0)不能直接写成if(sum)
L = mid;
else
R = mid;
}
printf("%.0lf\n",mid*100);
}
}