zoukankan      html  css  js  c++  java
  • ZOJ-3329 One Person Game (有环期望问题)

    题目大意:有3个骰子,各有k1,k2,k3个面,面值为1~ki。还有一个计数器,初始值为0,统计所有的面值和。每次同时置这三个骰子,如果第一个骰子的朝上的值为a、第二个值为b、第三个值为c,那么将计数器置为零。直到计数器的值大于n时结束,求次数的期望值。

    题目分析:这道题的状态转移方程不难写。定义状态dp(i)表示计数器值为 i 时还可以置几次,另外定义pk表示一次置出的3个骰子之和为k的概率,p0表示置出a、b、c的概率。则状态转移方程为:dp(i)= ∑pk*dp(i+k)+p0*dp(0)+1  <1>。到这儿就不知道怎么干了,查了下题解:定义dp(i)=A(i)*dp(0)+B(i),并将其代入<1>,得到A(i)= p0+∑pk*A(i+k),B(i)=1+ ∑pk*B(i+k)。那么只需要通过递推得到A(0)和B(0),就可以解得dp(0)=(1-A(0))/B(0)。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    
    int n,a,b,c;
    int k1,k2,k3;
    double A[600],B[600];
    double p[20];
    
    void init()
    {
        memset(p,0,sizeof(p));
        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)
                        p[i+j+k]+=1.0/k1/k2/k3;
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d%d%d%d%d%d",&n,&k1,&k2,&k3,&a,&b,&c);
            init();
            double p0=1.0/k1/k2/k3;
            memset(A,0,sizeof(A));
            memset(B,0,sizeof(B));
            for(int i=n;i>=0;--i){
                A[i]=p0;
                B[i]=1;
                for(int j=1;j<=k1+k2+k3;++j){
                    A[i]+=p[j]*A[i+j];
                    B[i]+=p[j]*B[i+j];
                }
            }
            printf("%.16lf
    ",B[0]/(1-A[0]));
        }
        return 0;
    }
    

      

  • 相关阅读:
    Android自动开关机实现
    List<T>的各种排序方法
    Struts、Ajax、Restful、Web Service 狂想曲框架实现篇(二)
    ArrayList和LinkedList性能比较
    Struts、Ajax、Restful、Web Service 狂想曲框架实现篇(三)
    ACM
    jquery
    安装IIS和部署网站的区别
    用IIS部署网站的问题和解决方案
    bug管理初识记录测试结果(外企)
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/5321700.html
Copyright © 2011-2022 走看看