90 分求助(提单仅差此题,急)
查看原帖
90 分求助(提单仅差此题,急)
552387
DeltaCR楼主2023/10/9 11:48

先大概说一下我的思路吧(以便各位大佬帮助)

一、输入:输入就不说了 (我好像已经说完了是吧)

二、-1 特判:输入的同时将一秒内所有设备消耗之和存入 sum,如果 sum <= p(说明每秒电量都不会减少),则输出 -1

三、二分查找:不需要 lower bound\text{lower bound} 或 upper bound\text{upper bound},普通二分即可

四、check(mid) 函数:采取贪心策略,有公式:

wi=max⁡(0,ai×time−bi)w_i=\max(0,a_i\times\text{time}-b_i)

(其中 wiw_i 为 time\text{time} 时间段内第 ii 个设备所需要充的电量),若

∑i=1nwi≤time×p\stackrel{n}{\underset{i=1}{\sum}}w_i\leq \text{time}\times 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 分,求调

2023/10/9 11:48
加载中...