题意简述
个人上电梯。每一秒,队列的第一个人都有 (每个时刻都是 ,不会变, )的概率上电梯。请求出 秒时电梯上人数的期望值。
思路框架
dp[i][j]表示第 时刻有 个人在电梯上的概率。最后用概率乘以数值求出期望(根据定义)。
具体思路
老样子,分两块
Part1. 设状态
首先 里面肯定有一维时间,这毫无疑问。然后我们发现,
- n,t只有2000,肯定不是让你线性过的,又不是A题
- 只有一维时间好像也无法转移
所以考虑加上一维人数。粗略估计珂以转移。
Part2. 转移
:时间为 ,电梯上有 个人的概率。
。其中 是上来一个人的概率, 是没上来人的概率。这个式子看起来很正确。但是我们考虑几个特殊情况
- j=0。这个的确需要考虑。而且这个时候j-1=-1,直接访问会RE。但是也不是不能转移,方程应该是dp[i][0]=dp[i-1][0]×(1-p)。也就是,我们要电梯上有0个人,那就要一直不上来,也就是一直乘以1-p。当然你也珂以认为它是(1-p)^i。
- j=n。如果上一秒已经到 个人了,这个时候队列已经空了。无论发生什么都还是 个人。所以 。
特判一下转移即珂。边界很显然,
代码
#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;
}