概率dp ZOJ 3329

本文介绍了一个涉及三个骰子的期望值计算问题,通过解析环状依赖的方法解决了传统递归过程中出现的相互依赖难题。文章分享了一种转换视角的思路,利用新的表达式避免了直接的环状依赖,并提供了详细的实现代码。
题意:给三个骰子,分别有k1,k2,k3个面,每个面朝上的概率相同。自己玩游戏,有一个计时器,计数器开始时为0,每次扔骰子,如果第一个为a,第二个为b,第三个为c就把计数器清零,否则计时器加上当前三个骰子的和,问当计数器大于n是的期望是多少
自己想的时候,求来求去都会发现是有环的,就是求a需要b,求b需要a,然后就不会了。。然后就百度了题解= =,这个题中也就是求dp[k]需要用dp[0],然后导dp[0]需要dp[k]。然后这道题用另外的一个式子表示了dp[k],使dp[0]只和这个式子中的系数有关,系数又能通过递推求出来,于是就能做了= =
代码:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int mod = 1e9+7;
#define ll long long
const int maxn = 610;
double a[maxn];
double b[maxn];
double p[100];
int main(){
    int T;
    cin>>T;
    while(T --){
        int n,ka,kb,kc,A,B,C;
        cin>>n>>ka>>kb>>kc>>A>>B>>C;
        for(int i = 0;i < maxn;i ++){
            a[i] = b[i] = 0.0;
        }
        double pp = 1.0/(ka*kb*kc);
        for(int i = 3;i < 100;i ++)p[i] = 0.0;
        for(int i = 1;i <= ka;i ++){
            for(int j = 1;j <= kb;j ++){
                for(int k = 1;k <= kc;k ++){
                    if(i == A&&j == B&&k == C)continue;
                    p[i+j+k] += pp;
                }
            }
        }
        for(int i = n;i >= 0;i --){
            for(int j = 3;j <= ka+kb+kc;j ++){
                a[i] += a[i+j]*p[j];
                b[i] += b[i+j]*p[j];
            }
            a[i] += pp;
            b[i] += 1.0;
            //cout<<a[i]<<' '<<b[i]<<endl;
        }
        printf("%.8lf\n",b[0]/(1-a[0]));
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值