先大概说一下我的思路吧(以便各位大佬帮助)
一、输入:输入就不说了 (我好像已经说完了是吧)
二、-1 特判:输入的同时将一秒内所有设备消耗之和存入 sum,如果 sum <= p(说明每秒电量都不会减少),则输出 -1
三、二分查找:不需要 lower bound 或 upper bound,普通二分即可
四、check(mid) 函数:采取贪心策略,有公式:
(其中 wi 为 time 时间段内第 i 个设备所需要充的电量),若
i=1∑nwi≤time×p则可行,否则不可行
代码如下
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n, p, a[N], b[N];
bool check(double tm /* 时间 */)
{
double sum = 0.0; // 统计 w[i] 之和
for (int i = 1; i <= n; ++i)
{
sum += max(0.0, a[i] * tm - b[i]); // 公式
}
return sum <= tm * p;
}
double _bsearch()
{
double l = 0, r = 1e15; // 高太大会溢出,1e15 没事
while (r - l > 1e-6) // 精度看题解说可以
{ // 以下都是二分查找的模板了
double mid = (l + r) / 2.0;
if (check(mid)) l = mid;
else r = mid;
}
return l;
}
int main()
{
ios::sync_with_stdio(false);
cin >> n >> p;
int sum = 0; // 用于 -1 特判的计数器
for (int i = 1; i <= n; ++i)
{
cin >> a[i] >> b[i];
sum += a[i]; // 累加 a[i]
}
if (sum <= p) // -1 特判
{
cout << -1 << endl;
return 0;
}
cout << setprecision(10) << fixed << _bsearch() << endl; // 保留 10 位小数
return 0;
}
90 分,求调