/**
链接:http://poj.org/problem?id=2976
题意:给定两组序列a b 去掉k个二元组(同一个i对应的a b) 使得a的总和除以b的总和最大;
分析: 对于任意二元组 a b 都存在 x = a / b + c ; c为待定数(表示二元组值与平均值的差值)
寻找最合适的 x 因此可以选择0作为差值点进行规划
化简后得到 -------->
b * x = a + c----> a - b * x = c ; 差值对于倍数的放大是不影响的(同增或同减);
因此可通过二分枚举x找到差值 找到差值后 需要最大化平均数 则需看差值和 和 0的大小关系
>=0 x 过小 ; <0 x 过大
那么 将这种化简目标表达式的方法也称之为0/1分数规划; 说白了 一般通过二分向着目标答案靠近;
可直接将目标进行化简为 a/b>=x ---> a-b*x>=0; 那么a-b*x就是所谓的构造数组;
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
const int maxn=1e3+7;
const double eps=1e-6;
int n,k,a[maxn],b[maxn];
bool judge(double x){
double tmp[maxn];
for(int i=0;i<n;i++) tmp[i]=a[i]-x*b[i];
sort(tmp,tmp+n);
double sum=0;
for(int i=k;i<n;i++) sum+=tmp[i];
return sum>=0.0;
}
int main (){
while(~scanf("%d %d",&n,&k)){
if(n==0&&k==0) break;
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<n;i++) scanf("%d",&b[i]);
double l=0,r=1.0;
while(fabs(r-l)>eps){
double mid=(l+r)/2;
if(judge(mid)) l=mid;
else r=mid;
}
int ans=(int)(l*100+0.50);
printf("%d\n",ans);
}
return 0;
}
POJ - 2976 最大化平均值....
猜你喜欢
转载自blog.csdn.net/hypHuangYanPing/article/details/81105062
今日推荐
周排行