题解 P3743 【kotori的设备】
本题可以使用二分答案的解法。
对于二分答案,就是利用二分算法来找到答案,如果当前答案可行,则最终的答案一定大于等于它,否则最终的答案小于等于它。
二分部分代码:
l=0.0;
r=3000000001.0;//如果定1e9,会发现有一个测试点过不了,因为答案大于1e9。
while(l<=r-1e-6)//题目中误差不得大于1e-4,这里我定1e-6可以免得卡精度。
{
mid=(l+r)/2;
if(check(mid))//判断答案是否可行。
{
l=mid;
}
else {
r=mid;
}//二分答案。
}
printf("%lf",r);
我们还需要一个
int check(double m)
{
double c=0;
for(int i=1;i<=n;i++)
{
if(a[i]*m>b[i])
c+=(a[i]*m-b[i]);//如果设备原有电量不够用,那么必须充电。
}
c-=p*m;
if(c>0.0)return 0;
return 1;
//最后判断要充的电量是否小于等于可充的电量,是则返回真,否则为假。
}
还有一个特判:如果所有设备单位时间的用电量小于等于充电器单位时间的充电量,则可以无限使用,输出
double c=0;
for(int i=1;i<=n;i++) c+=a[i];
if(c-p<=0.0){
printf("-1");
return 0;
}
完整代码:
#include<bits/stdc++.h>
using namespace std;
int n;
double p;//我定double,防止卡精度。
double a[100001],b[100001];
double l,r,mid;
int check(double m)
{
double c=0;
for(int i=1;i<=n;i++)
{
if(a[i]*m>b[i])
c+=(a[i]*m-b[i]);//如果设备原有电量不够用,那么必须充电。
}
c-=p*m;
if(c>0.0)return 0;
return 1;
//最后判断要充的电量是否小于等于可充的电量,是则返回真,否则为假。
}
int main()
{
scanf("%d%lf",&n,&p);
for(int i=1;i<=n;i++)scanf("%lf%lf",&a[i],&b[i]);
double c=0;
for(int i=1;i<=n;i++) c+=a[i];
if(c-p<=0.0){
printf("-1");
return 0;
}
l=0.0;
r=3000000001.0;//如果定1e9,会发现有一个测试点过不了,因为答案大于1e9。
while(l<=r-1e-6)//题目中误差不得大于1e-4,这里我定1e-6可以免得卡精度。
{
mid=(l+r)/2;
if(check(mid))//判断答案是否可行。
{
l=mid;
}
else {
r=mid;
}//二分答案。
}
printf("%lf",r);
}