传送门:>Here<
题意:有n个人排队做电梯,每个人必须等前面的人全部上了以后才能上。对于每秒钟,有p的概率选择上电梯,(1-p)的概率选择不上电梯。现在问t秒期望多少人上电梯
解题思路:
期望DP。
$f[i][j]$表示第i秒上了j个人的概率。
$f[1][1] = p, f[1][0] = (1 - p)$,并且$f[i][0]$都需要初始化。($* (1 - p)$)
这题好像和普通的期望DP不太一样啊,因为f数组设的是概率而不是期望。这样设的话答案就应该是$\sum\limits_{i = 0}^{Min(n, t)}f[t][i] * i$
考虑如何转移:
第i秒的时候不上人:$ f[i-1][j] * (1 - p) $
第i秒的时候上人:$ f[i-1][j-1] * p $
因此对于一般情况:$$f[i][j] = f[i-1][j] * (1 - p) + f[i-1][j-1] * p$$
另外,总共就n个人,如果$t > n$就需要特判了:$$f[i][n] = f[i-1][n] + f[i-1][n-1]*p$$
Code
还是边界条件!对于$f[i][j]$,由于每秒最多上一个人,所以$j$是不可能大于$i$的,要特判一下。
/*By QiXingzhi*/
#include <cstdio>
#include <queue>
#define r read()
#define Max(a,b) (((a)>(b)) ? (a) : (b))
#define Min(a,b) (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
const int N = ;
const int INF = ;
inline int read(){
int x = ; int w = ; register int c = getchar();
while(c ^ '-' && (c < '' || c > '')) c = getchar();
if(c == '-') w = -, c = getchar();
while(c >= '' && c <= '') x = (x << ) +(x << ) + c - '', c = getchar();
return x * w;
}
int n,t;
double p,f[N][N],cur,ans;
int main(){
// freopen(".in", "r", stdin);
scanf("%d %lf %d",&n,&p,&t);
f[][] = p;
f[][] = -p;
for(int i = ; i <= t; ++i){
f[i][] = f[i-][] * (-p);
}
for(int i = ; i <= t; ++i){
for(int j = ; j <= n; ++j){
if(j > i){
break;
}
f[i][j] = f[i-][j]*(-p) + f[i-][j-]*p;
}
f[i][n] = f[i-][n] + f[i-][n-] * p;
}
for(int i = ; i <= n; ++i){
if(i > t) break;
ans += f[t][i] * i;
}
printf("%.8lf", ans);
return ;
}