CodeForces 518D - R2D2 and Droid Army(概率dp)
题意:n个人排成一队按队伍序列上扶梯,共 t 时刻,每时刻最多进一个人,进的概率为p,已经进去的人不能再出来,若排在队首的不进则后边的人无法进,求 t 时刻后扶梯上人数的数学期望。
一维表示时刻,二维表示人数,有状态转移方程
dp[ i + 1 ] [ j + 1 ] = dp[ i ] [ j ] * p; //这一时刻进了一个人
dp[ i + 1 ] [ j ] = dp[ i ] [ j ] * (1.0 - p); //这一时刻未进人
赋初值时,0时刻必为0个人,dp[0][0] = 1.0;
统计结果时,
对于0 <= i < n 的部分,即为 dp[ t ] [ i ] * i;
对于n <= i <= t 的部分,即为dp[ i ] [ n ] * n;
#include<cstdio> #include<cstring> #include<cctype> #include<cstdlib> #include<cmath> #include<iostream> #include<sstream> #include<iterator> #include<algorithm> #include<string> #include<vector> #include<set> #include<map> #include<deque> #include<queue> #include<stack> #include<list> typedef long long ll; typedef unsigned long long llu; const int MAXN = 2000 + 10; const int MAXT = 10000 + 10; const int INF = 0x7f7f7f7f; const double pi = acos(-1.0); const double EPS = 1e-6; using namespace std; int n, t; double p, ans, dp[MAXN][MAXN]; int main(){ ans = 0.0; scanf("%d%lf%d", &n, &p, &t); memset(dp, 0, sizeof dp); dp[0][0] = 1.0; for(int i = 0; i <= t; ++i){ for(int j = 0; j < n; ++j){ dp[i + 1][j + 1] += dp[i][j] * p; dp[i + 1][j] += dp[i][j] * (1.0 - p); } } for(int i = 0; i < n; ++i) ans += dp[t][i] * (double)i; for(int i = n; i <= t; ++i) ans += dp[i][n] * (double)n; printf("%.8lf\n", ans); return 0; }