题目链接
题意:
给出两个长度为 n n n的数组 a a a, b b b,选择 k k k 个下标 p [ 1 ] , p [ 2 ] , . . . p [ k ] p[1],p[2],...p[k] p[1],p[2],...p[k] ,同时将 a a a, b b b 数组中的这些下标删除,得到的数组的权值为
∑ a [ i ] ∑ b [ i ] \frac {\sum a[i]}{\sum b[i]} ∑b[i]∑a[i] ,求最大权值是多少?
题解:
经典的01分数规划问题,考虑二分最大值 m i d mid mid。 那么式子就要满足 ∑ a [ i ] ∑ b [ i ] ≥ m i d \frac {\sum a[i]}{\sum b[i]} \geq mid ∑b[i]∑a[i]≥mid
移项: ∑ ( a [ i ] − m i d ⋅ b [ i ] ) ≥ 0 \sum (a[i]-mid \cdot b[i]) \geq 0 ∑(a[i]−mid⋅b[i])≥0 ,此时我们将 a [ i ] − m i d ⋅ b [ i ] a[i]-mid \cdot b[i] a[i]−mid⋅b[i]看做一个整体进行排序,即我们要选最大的 n − k n-k n−k 个数,然后判断是否 ≥ 0 \geq 0 ≥0 ,满足则 l = m i d l=mid l=mid,反之 r = m i d r=mid r=mid。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int>pii;
const int MAXN=1e5+5;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double eps = 1e-6;
ll a[MAXN];
ll b[MAXN];
double c[MAXN];
int main()
{
int n,k;
while(scanf("%d%d",&n,&k)&&n&&k)
{
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
double l=0,r=1000;
while(r-l>eps)
{
double mid=(l+r)/2;
for(int i=1;i<=n;i++) c[i]=a[i]-mid*b[i];
sort(c+1,c+1+n);
double s=0;
for(int i=n;i>k;--i)s+=c[i];
if(s>=0) l=mid;
else r=mid;
}
printf("%.0f\n",l*100);
}
}