Gym 101666L(简单dp)

版权声明:本文为博主原创文章,转载请标明博主信息:https://blog.csdn.net/weixin_39453270 https://blog.csdn.net/weixin_39453270/article/details/82502754

传送门:

题面:

    PDF

题意:

    你最开始有1升的pink饮料,你想要获得blue饮料,现在有n个人,每个人都希望用O饮料换取W饮料,每次的转化率为R。现在你可以跟他们依次的交换饮料,而当你最后得到10升以上的blue饮料后,多余10升的你将抛弃,问你最多能获得多少blue饮料。

题目分析:

    简单的线性dp,令dp[i]为当前编号为i的饮料能够换取的饮料体积,则有转移方程

    但是这个题目中,因为人数最多为1e5,而每次可能使得体积*2,因此如果像上面一样递推,则必定会导致爆double。

    因此我们需要考虑将每次的汇率化为log2的形式,并将转移方程变为:转移,最后变为原值即可。

代码:

#include <bits/stdc++.h>
#define maxn 100005
using namespace std;
struct drink{
    string O,W;
    double rate;
}q[maxn];
map<string,int>mp;
const double INF=1e200;
double dp[maxn];
int main()
{
    int n;
    scanf("%d",&n);
    int cnt=1;
    mp["pink"]=1;
    for(int i=1;i<=n;i++){
        cin>>q[i].O>>q[i].W>>q[i].rate;
        if(!mp.count(q[i].O)) mp[q[i].O]=++cnt;
        if(!mp.count(q[i].W)) mp[q[i].W]=++cnt;
        q[i].rate=log2(q[i].rate);
    }
    for(int i=1;i<=cnt;i++) dp[i]=-INF;
    dp[1]=0;
    for(int i=1;i<=n;i++){
        int idW=mp[q[i].W],idO=mp[q[i].O];
        dp[idO]=max(dp[idO],dp[idW]+q[i].rate);
    }
    if(!mp.count("blue")) puts("0.0000000000");
    else{
        double res=dp[mp["blue"]];
        if(res>log2(10)) puts("10.000000000");
        else printf("%.14f\n",min(10.0,pow(2,res)));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_39453270/article/details/82502754
今日推荐