01分数规划,就是这样一个东西
\(max(\frac{\sum ai * xi}{\sum bi * xi})\),其中\(xi \in {0,1}\)
简而言之,就是在n个物品中选出任意几个【或者可以有限制选多少个】,使得其两种权值a,b的比值最大
这样的问题可以二分解决
假如有这样一道裸题:POJ2976,选n - k个物品使得比值最大
我们二分出r,
若存在\(\frac{\sum ai * xi}{\sum bi * xi} >= r\),则r可行
变形得\(\sum ai * xi - r * \sum bi * xi >= 0\)
我们就可以把每件物品看做是权值\(ai - bi * r\),排个序看看前n - k大之和是否大于0即可
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
using namespace std;
const int maxn = 1005,maxm = 100005,INF = 1000000000;
int n,k;
double A[maxn],B[maxn],t[maxn];
bool check(double x){
REP(i,n) t[i] = A[i] - x * B[i];
sort(t + 1,t + 1 + n);
double sum = 0;
for (int i = k + 1; i <= n; i++) sum += t[i];
return sum > 0;
}
int main(){
while (~scanf("%d%d",&n,&k) && (n || k)){
REP(i,n) scanf("%lf",&A[i]);
REP(i,n) scanf("%lf",&B[i]);
double l = 0,r = 1.0,mid;
while (r - l > 0.0000001){
mid = (l + r) / 2;
if (check(mid)) l = mid;
else r = mid;
}
printf("%d\n",(int)round(l * 100));
}
return 0;
}