题目
https://www.luogu.com.cn/problem/P4653
思路
最大化可能的最小收益,最大值最小,想必大家已经熟悉二分题的这个套路了。枚举一个值x,模拟,检验是否能选A和选B的收益都达到x。
显然要先选权值大的灯,所以我们降序排序。
关于这个检验,我用的是最暴力的方法,若A不行,就加到它行;再看B,也是如此。注意因为选取灯泡有花费,成本变高,这时A又不一定可行了,之后我们反复横跳,直到AB都满足条件。
若可以出现AB都满足的情况,则该x值可行。
代码
#include<cstdlib>
#include<algorithm>
#define inf 0x3f3f3f3f
#define eps 1e-6
#define maxn (int)(1e6+10)
#define db double
using namespace std;
int n;
db a[maxn],b[maxn];
int ok(db x){
int i=0,j=0;
db suma=0,sumb=0;
while(suma-i-j<x||sumb-i-j<x){
while(suma-i-j<x){
if(i>n) return 0;
suma+=a[++i];
}
while(sumb-i-j<x){
if(j>n) return 0;
sumb+=b[++j];
}
}
return 1;
}
bool cmp(db x,db y){
return x>y;
}
int main(){
int i,j;
db l,r,mid;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%lf%lf",&a[i],&b[i]);
sort(a+1,a+n+1,cmp);
sort(b+1,b+n+1,cmp);
l=0;r=inf;
while(r-l>eps){
mid=(l+r)/2.0;
if(ok(mid)) l=mid;
else r=mid;
}
printf("%.4lf",l);
// system("pause");
return 0;
}