1.因为充电器在任意时刻给任意机器充电,并且交换充电对象并不消耗时间,所以可以从整体来看,如果充电器每秒可以冲的电量p大于等于全部机器的每秒消耗的电量的话,相当于可以利用充电器做到,让每台机器的电量始终大于等于它的原电量,也就是每台机器电量只可能增不可能减,所以可以无限使用下去。2.若不能无限的使用下去的话,因为使用的时间越长,出现某个机器电量为0的概率就越大可以理解为1111000000(1代表可以使用到该时刻,0代表不能使用到该时刻)可以看出具有单调性,那就通过二分求出能使用的最长时间。二分的话主要就是要考虑check函数,按每个机器不充电能使用到的最大时间排个序,然后依次取到mid时刻,详细的见注释。
#include<bits/stdc++.h>
using namespace std;
#define eps 1e-7
struct node
{
double a,b,time;
}ma[1000000+10];
double p;
int n;
bool cmp(const node&a,const node&b)
{
return a.time<b.time;
}
bool check(double mid)
{
double tmp=0;
for(int i=0;i<n;i++)
{
if(ma[i].time>mid) break;
tmp+=(mid-ma[i].time)*ma[i].a;//因为要判断能不能使用到mid时刻,所以要把在mid时刻之前就没电的机器充上电才行,这步操作是计算给这些没电了的机器充电需要消耗的电量。
}
return mid*p>=tmp;若充电器能提供的电量>=需要的电量则mid满足
}
int main()
{
double tmp=0;
cin>>n>>p;
for(int i=0;i<n;i++)
{
cin>>ma[i].a>>ma[i].b;
ma[i].time=ma[i].b/ma[i].a;
tmp+=ma[i].a;
}
if(p>=tmp)
{
cout<<-1<<endl;
return 0;
}
sort(ma,ma+n,cmp);
double low=0,up=1e11+100,mid;//这个上限我一开始开小了,过不了,看了别人的就改大过了
while(up-low>=eps)
{
mid=(low+up)/2;
if(check(mid))
low=mid;
else
up=mid;
}
printf("%.10lf
",low);
return 0;
}