Codeforces 518D Ilya and Escalator 题解

博客观赏效果更佳

题意简述

n ( < = 2000 ) n(<=2000) 个人上电梯。每一秒,队列的第一个人都有 p p (每个时刻都是 p p ,不会变, 0 < = p < = 1 0<=p<=1 )的概率上电梯。请求出 t ( < = 2000 ) t(<=2000) 秒时电梯上人数的期望值。

思路框架

dp[i][j]表示第 i i 时刻有 j j 个人在电梯上的概率。最后用概率乘以数值求出期望(根据定义)。

具体思路

老样子,分两块

Part1. 设状态

首先 d p dp 里面肯定有一维时间,这毫无疑问。然后我们发现,

  1. n,t只有2000,肯定不是让你线性过的,又不是A题
  2. 只有一维时间好像也无法转移
    所以考虑加上一维人数。粗略估计珂以转移。

Part2. 转移

d p [ i ] [ j ] dp[i][j] :时间为 i i ,电梯上有 j j 个人的概率。

d p [ i ] [ j ] = d p [ i 1 ] [ j 1 ] × p + d p [ i 1 ] [ j ] × ( 1 p ) dp[i][j]=dp[i-1][j-1]\times p+dp[i-1][j]\times (1-p) 。其中 p p 是上来一个人的概率, 1 p 1-p 是没上来人的概率。这个式子看起来很正确。但是我们考虑几个特殊情况

  1. j=0。这个的确需要考虑。而且这个时候j-1=-1,直接访问会RE。但是也不是不能转移,方程应该是dp[i][0]=dp[i-1][0]×(1-p)。也就是,我们要电梯上有0个人,那就要一直不上来,也就是一直乘以1-p。当然你也珂以认为它是(1-p)^i。
  2. j=n。如果上一秒已经到 n n 个人了,这个时候队列已经空了。无论发生什么都还是 n n 个人。所以 d p [ i ] [ n ] = d p [ i 1 ] [ n 1 ] × p + d p [ i 1 ] [ n ] dp[i][n]=dp[i-1][n-1]\times p+dp[i-1][n]

特判一下转移即珂。边界很显然, d p [ 0 ] [ 0 ] = 1.00 dp[0][0]=1.00

代码

#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
    #define N 2333
    #define real double
    #define F(i,l,r) for(int i=l;i<=r;++i)
    #define D(i,r,l) for(int i=r;i>=l;--i)
    #define Fs(i,l,r,c) for(int i=l;i<=r;c)
    #define Ds(i,r,l,c) for(int i=r;i>=l;c)
    #define Tra(i,u) for(int i=G.Start(u),__v=G.To(i);~i;i=G.Next(i),__v=G.To(i))
    #define MEM(x,a) memset(x,a,sizeof(x))
    #define FK(x) MEM(x,0)

    int n,t;real p;
    void Input()
    {
        scanf("%d%lf%d",&n,&p,&t);
    }

    real dp[N][N];
    void Soviet()
    {
        FK(dp);
        dp[0][0]=1.00;
        F(i,1,t)
        {
            F(j,0,n)
            {
                if (j==0) dp[i][j]=dp[i-1][j]*(1-p);
                else if (j==n) dp[i][j]=dp[i-1][j-1]*p+dp[i-1][j];
                else dp[i][j]=dp[i-1][j-1]*p+dp[i-1][j]*(1-p);

                // printf("dp[%d][%d]=%.3f\n",i,j,dp[i][j]);
            }
        }
        real ans=0.00;
        F(i,1,n) ans+=dp[t][i]*i;
        printf("%.6f\n",ans);
    }

    #define Flan void
    Flan IsMyWife()
    {
        Input();
        Soviet();
    }
}
int main()
{
    Flandre_Scarlet::IsMyWife();
    getchar();getchar();
    return 0;
}
发布了210 篇原创文章 · 获赞 8 · 访问量 8992

猜你喜欢

转载自blog.csdn.net/LightningUZ/article/details/103338648