One Person Game ZOJ - 3329 期望dp

题意:有三个骰子,分别有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])+p0dp[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++)
                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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值