群巨救我……(期望DP)
题目链接:https://ac.nowcoder.com/acm/contest/17583/E
题目来源:牛客网
Problem Description
众所周知,牛可乐 的口胡能力十分强大
牛可乐 要讲 n 件事情,我们把这些事情从 1∼n 标号。
牛可乐每讲一件事需要耗费一个单位的时间,但是牛可乐讲事情和普通人不同:牛可乐在讲完 第 i 件事时,只有 p i {p_i} pi的概率继续讲下一件事(第 i+1 件),也就是说,牛可乐讲完第 i 件事后有 (1- p i p_i pi)的概率从第 i-1 件事开始讲!
当牛可乐讲完第 n 件事,并且决定讲下一件事时,牛可乐才算是把这n件事讲完了。
牛妹是个不耐烦的女孩子,她想问问你牛可乐期望要讲多久才能把n件事情全部讲完。
Input
第一行一个整数 n
第二行 n 个浮点数,代表 p i p_i pi,保证 p 1 p_1 p1=1
Output
一行一个浮点数,表示 牛可乐期望要多久才能把全部事情讲完(保留到小数点后 3 位)
Sample Input
4
1 0.6 0.4 0.2
Sample Output
38.333
Remark
对于 20% 的数据,1 ≤ \le ≤ n ≤ \le ≤ 20
对于 100%的数据,1 ≤ \le ≤ n ≤ \le ≤ 1 0 5 10^5 105
Solution
这题需要计算数学期望,因为实际上存在无数种情况把n件事情全部讲完,因此普通的计算数学期望的方法并不太可行,此时需要借助动态规划的思想:
设 f i f_i fi表示从第一件事讲到第i件事所需要的时间。那么显然答案就是 f n f_{n} fn。
那么 f i f_i fi会由哪些状态转移呢?
- f i f_i fi有 p i p_i pi的概率:直接由 f i − 1 f_{i-1} fi−1转移过来
- f i f_i fi有 1 − p i 1-p_i 1−pi的概率:由 f i − 1 f_{i-1} fi−1先转移到 f i − 2 f_{i-2} fi−2,再由 f i − 2 f_{i-2} fi−2回到 f i f_{i} fi
∴ 状态转移方程就该为:
f i = p i − 1 ∗ ( f i − 1 + 1 ) + ( 1 − p i − 1 ) ∗ ( f i − 1 + 1 + f i − f i − 2 ) f_i=p_{i-1}*(f_{i-1}+1)+(1-p_{i-1})*(f_{i-1}+1+f_i-f_{i-2}) fi=pi−1∗(fi−1+1)+(1−pi−1)∗(fi−1+1+fi−fi−2)
其 中 , f i − f i − 2 表 示 从 i − 2 讲 到 i 所 需 的 时 间 其中,f_i-f_{i-2}表示从i-2讲到i所需的时间 其中,fi−fi−2表示从i−2讲到i所需的时间
移项化简得:
f i = ( f i − 1 + 1 + ( p i − 1 − 1 ) ∗ f i − 2 ) / p i − 1 f_i=(f_{i-1}+1+(p_{i-1}-1)*f_{i-2})/p_{i-1} fi=(fi−1+1+(pi−1−1)∗fi−2)/pi−1
Code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+100;
int n;
double f[N],p[N];
void solve()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lf",p+i);
// 公式推导
// f[i]=p[i-1]*(f[i-1]+1)+(1-p[i-1])*(f[i-1]+1+f[i]-f[i-2])
// -> f[i]=(f[i-1]+1+(p[i-1]-1)*f[i-2])/p[i-1]
f[1]=1;
for(int i=2;i<=n;i++)
{
f[i]=(f[i-1]+1+(p[i-1]-1)*f[i-2])/p[i-1];
}
printf("%.3lf\n",f[n]);
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
solve();
/*
*
* ┏┓ ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃ ┃
* ┃ ━ ┃ ++ + + +
* ████━████+
* ◥██◤ ◥██◤ +
* ┃ ┻ ┃
* ┃ ┃ + +
* ┗━┓ ┏━┛
* ┃ ┃ + + + +Code is far away from
* ┃ ┃ + bug with the animal protecting
* ┃ ┗━━━┓ 神兽保佑,代码无bug
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛ + + + +
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛+ + + +
*/
}
最后感谢小伙伴们的学习噢~