思路:
题目本质上是考虑函数 y = sigma(vi) - x * sigma(ci), 使得y尽可能的接近于0.
我们可以给定x, 然后考虑是否存在一种取数方案,使得y > 0
如果存在某种取数方案使得y > 0, 则说明在这种的取数方案下,x还可以继续放大,使得y更加接近于0.(l=mid)
否则,x还可以继续缩小,即(r = mid)
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <algorithm>
#include <math.h>
#include <iomanip>
using namespace std;
const int maxN = 205;
int n, m;
double v[maxN], c[maxN];
//计算在给定x的情况下,y = sigma(vi) - x * sigma(ci)的最大值
//若y的最大值 > 0, 即,存在一组取数的方案,使得在给定x的情况下,y > 0
//因为当y == 0时, x 才等于 sigma(vi) / sigma(ci), 为了使y尽可能靠近0,所以x可以继续放大(l = mid)。
double getF(double x) {
double t[maxN];
for (int i = 0; i < n; i++) t[i] = v[i] - x * c[i];
//y的最大值,必然是取前m大的t[i]和
sort(t, t + n);
//取前m个
double sum = 0;
for (int i = n; i >= n - m; i--) sum += t[i];
return sum;
}
bool check(double x) {
if (getF(x) > 0) return false;//f的最小值大于0,x还可以放大,即l = mid;
else return true;
}
int main() {
double maxR = 0;
cin >> n >> m;
for (int i = 0; i < n; i++) cin >> v[i];
for (int i = 0; i < n; i++) {
cin >> c[i];
maxR = max(maxR, v[i] / c[i]);
}
double l = 0, r = maxR + 1, res = 0;
while (fabs(r - l) > 0.0001) {
double mid = (l + r) / 2;
if (check(mid)) r = mid;
else l = mid;
}
cout << setprecision(3) << fixed << r << endl;
return 0;
}