Gym 101666L(簡單dp)
阿新 • • 發佈:2019-02-20
傳送門:
題面:
題意:
你最開始有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; }