Gym 101666L(简单dp)
传送门:
题面:
题意:
你最开始有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;
}