P4712 「生物」能量流动

题目描述
生物课上,小 F 学习到了食物链、食物网的相关内容。

他学到,能量是逐级递减的。比如在食物链上,两个链接起来的生物 A \rightarrow BA→B(意思是 BB 吃 AA)之间的能量传递效率最多只有 \frac 1 5
5
1

;而研究种间关系,能够使能量流向对人类最有益的部分。

现在,小 F 想研究一下能量流动的关系,于是他在脑海里创造了一个生态的系统。

在这个生态的系统里,有 n+2n+2 种生物,其中 00 是生产者,整个生态系统所流经的能量由它固定;你是贪婪的顶级掠食者 n + 1n+1,可以捕食所有生物;其他的掠食者 [1, n][1,n] 各有各的喜好,只会捕食编号在 [0, r_i][0,r
i

] 的生物。由于天然形成的强弱顺序,上述关系满足 r_i \leq r_{i + 1}(1 \leq i < n),r
i

≤r
i+1

(1≤i<n), r_i < i(1 \leq i \leq n)r
i

<i(1≤i≤n)。

每种动物需要摄取至少 a_ia
i

单位能量才能存活;一个生物摄取到的能量可以传递给捕食者,但传递效率都不超过 \frac 1 5
5
1

。也就是说,假设该动物捕获了 b_ib
i

单位的能量,所有捕食它的掠食者得到的能量总和 c_ic
i

,那么有:

b_i \geq a_ib
i

≥a
i

c_i \leq \frac 1 5 b_ic
i


5
1

b
i

你希望知道,在所有生物都存活的情况下,在最优情况下你能获取到的最大能量是多少。

输入格式
输入第一行两个个整数 n, a_0(1 \leq n \leq 10 ^ 5, 1 \leq a_0 \leq 10 ^ 9)n,a
0

(1≤n≤10
5
,1≤a
0

≤10
9
)。a_0a
0

是生产者固定的能量值。

接下来 nn 行,每行 22 个正整数,表示 a_i, r_i(1 \leq a_i \leq 10 ^ 9)a
i

,r
i

(1≤a
i

≤10
9
)。

数据保证,0\leq r_i < i, r_i \leq r_{i + 1}0≤r
i

<i,r
i

≤r
i+1

输出格式
输出一行一个浮点数,表示你——顶级掠食者——能得到的最大能量。如果不能使得所有生物存活(包括你自己),请输出 -1−1。

你的答案与参考答案的相对误差或者绝对误差不超过 10 ^ {-8}10
−8
即被认为是正确的。如果你的程序是正确的,可以不用考虑精度问题。

输入输出样例
输入 #1复制
2 9
1 0
1 1
输出 #1复制
0.2000000
输入 #2复制
2 9
1 0
1 0
输出 #2复制
-1
输入 #3复制
2 10
1 0
1 0
输出 #3复制
0.4000000
说明/提示
样例 1 解释
最优情况下:

1 号掠食者捕食生产者 0,捕食 5 点能量,传递效率为 \frac 1 5
5
1

,得到 1 点能量。
2 号掠食者捕食生产者 0,捕食 4 点能量,传递效率为 \frac 1 5
5
1

,得到 0.8 点能量。
2 号掠食者捕食掠食者 1,捕食 1 点能量,传递效率为 \frac 1 5
5
1

,得到 0.2 点能量。
可怜的你只能捕获 2 号掠食者的能量,捕食 1 点能量,得到 0.2 点能量。

样例 2, 3 解释
由于 2 号掠食者开始减肥不吃肉了(也有可能是打不过 1 了),所以所需的生产者能量从 9 点变成了 10 点。

子任务
子任务 1(21 \mathrm{pts}) : n \leq 1001(21pts):n≤100;

子任务 2(89 \mathrm{pts}) : n \leq 10 ^ 52(89pts):n≤10
5

#include <bits/stdc++.h>
using namespace std;
//贪心算法,对于每个动物,尽量吃编号靠前的以最小化能量流失
//满足所有生物需求后,剩下的是我们所能获取的最大能量
long long n,t,ans=0;//全局变量默认初始值为0;
long long int a[100002],r[100002];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);//加快执行速度
    cin>>n>>a[0];
    ans=a[0];
    for(int i=1; i<=n; i++)//此循环不包括人
    {
        cin>>a[i]>>r[i];//输入每种生物至少需要摄取的能量a[i]和最多能捕食的层的上限
        for(int j=t+1; j<=r[i]; j++)//从上一生物捕食的层数的上限循环到该生物捕食层的上限
        {
            ans+=a[j];//计算剩余能量之和
        }
        t=r[i];
        ans-=5*a[i];//判断余量是否足够下一层生物存活
        if(ans<0)
            cout<<"-1",exit(0);
    }
    for(int i=t+1;i<=n;i++)
    {
        ans+=a[i];
    }
    printf("%.8lf",ans/5.0);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值