您的位置:首页 > 其它

One Person Game ZOJ - 3329 期望dp

2017-11-05 00:39 429 查看
题意:有三个骰子,分别有k1,k2,k3面,上面的数字1到k1,1到k2,1到k3.每个面出现的概率相同

游戏规则是:

1,有一个计数器,从0开始计数

2.每次摇三个骰子,如果第一个骰子摇到a,第二个骰子摇到b,第三个骰子摇到c,那么计数器归零,否则计数器加上他们三个骰子摇出来的数

3.如果计数器的数字不大于n,那么重复第2步。

问这个游戏结束的期望

分析:

dp[i]:计数器的数字是i,离游戏结束的期望

p[i]:三个骰子数相加是i的概率

p0:计数器归零的概率

dp[i]=∑(dp[i+k]∗p[k])+p0∗dp[0]

但是这个dp[0]是我们要求的啊…

如果成环了可以用高斯

这里可以转化一下系数

设 dp[i]=A[i]*dp[i]+B[i];

带入到上面的式子中就可以得到

A[i]=∑(p[k]∗A[k+i])+p0

B[i]=∑(B[i+k]∗p[k])+1

然后递推就行了

using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn =  600;
double A[maxn],B[maxn],p[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
mem(A,0);mem(B,0);mem(p,0);
int n,k1,k2,k3,a,b,c;
scanf("%d %d %d %d %d %d %d",&n,&k1,&k2,&k3,&a,&b,&c);
for(int i=1;i<=k1;i++)
for(int j=1;j<=k2;j++)

a3ad
for(int k=1;k<=k3;k++)
{
if(i==a&&j==b&&k==c) continue;
p[i+j+k]++;
}
for(int i=0;i<=k1+k2+k3;i++) p[i]=p[i]/(k1*k2*k3);
p[0]=1.0/(k1*k2*k3);
for(int i=n;i>=0;i--)
{
for(int j=3;j<=(k1+k2+k3);j++)
{ A[i]+=A[i+j]*p[j];B[i]+=B[i+j]*p[j];}
A[i]=A[i]+p[0];B[i]+=1;
}
printf("%.15f\n",B[0]/(1.0-A[0]));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: