zoukankan      html  css  js  c++  java
  • uva 10759 Dice Throwing

    数学题(概率基本知识+DP记忆化搜索实现)

    题意:概率题:丢n个骰子,和大于等于x的概率是多少,用反面来求,1-小于x的概率

    首先丢n个骰子,可以看做是依次丢的(独立重复试验),每次丢的点数记录下来,比如3个筛子123和132是不同的,所以就是一个排列(而不是组合),那么总的可能为6^n,要用long long 保存。然后再找出有多少个排序和和是小于x的。这个找特殊排列的过程用DP来构建才不能超时(我用的是记忆化搜索,当然递推也是可以的,仿照记忆化搜索来写的,个人更倾向于记忆化搜索,容易理解,而且应该很多没用的状态不会去到,但是递推会推出所有状态)

    记忆化搜索,开一个二维数组dp[i][j],表示现在的点数是x-i点,还要丢n-j次骰子(其实就可以理解为,还有i点才会到0,已经丢了j次骰子)

    那么当前要丢骰子,骰子的点数要满足i-k>0,最后才能使丢了n个骰子的和小于x

    然后显然dp[i][j]= dp[i-k][j+1]和累加和

     

    #include <cstdio>
    #include <cstring>
    #define N 30
    #define M 160
    long long dp[M][N],tot;
    
    long long dfs(long long m , int c)  //m是当前的点数,c是第几个骰子
    {
        if(dp[m][c]!=-1) 
            return dp[m][c];
        dp[m][c]=0;
        for(int i=1; i<=6; i++)
            if(m-i>0)
                dp[m][c]+=dfs(m-i,c+1);
        return dp[m][c];
    }
    long long gcd(long long a ,long long b)
    {
        return b==0?a:gcd(b,a%b);
    }
    int main()
    {
        long long n,m;
        long long de,nu,tmp;  //分母和分子
        while(scanf("%lld%lld",&n,&m)!=EOF)
        {
            if(!n && !m) break;
            de=1;
            for(int i=1; i<=n; i++)
                de*=6;   //总状态数
            tot=0;  //记录要多少种排列(个数一定为n)的总和小于等于m
            memset(dp,-1,sizeof(dp));
            for(int i=0; i<=m; i++)
                dp[i][n]=1;  //这个不要漏
            dp[m][0]=dfs(m,0);
            nu=de-dp[m][0];
            tmp=gcd(de , nu);
            //printf("dp结果=%lld\n",dp[m][0]);
            //printf("分子=%lld\n",nu);
            //printf("分母=%lld\n",de);
            //printf("gcd=%lld\n",tmp);
            if(nu/tmp==0)
                printf("0\n");
            else if(nu/tmp==de/tmp)
                printf("1\n");
            else
                printf("%lld/%lld\n",nu/tmp , de/tmp);
        }
        return 0;
    }

    递推版本

    #include <cstdio>
    #include <cstring>
    #define N 30
    #define M 160
    long long dp[M][N];
    long long n,m;
    long long de,nu,tmp;  //分母和分子
    
    long long gcd(long long a ,long long b)
    {
        return b==0?a:gcd(b,a%b);
    }
    void DP()
    {
        de=1;
        for(int i=1; i<=n; i++) de*=6;   //总状态数
        memset(dp,0,sizeof(dp));
        for(int i=0; i<=m; i++) dp[i][n]=1;
    
        for(int i=n-1; i>=0; i--)  
            for(int j=0; j<=m; j++)
                for(int k=1; k<=6; k++)
                    if(j>k)
                        dp[j][i]+=dp[j-k][i+1];
        //printf("%lld\n",dp[m][0]);
        nu=de-dp[m][0];
    }
    int main()
    {
        while(scanf("%lld%lld",&n,&m)!=EOF)
        {
            if(!n && !m) break;
            DP();  //递推构建
            tmp=gcd(de , nu);
            //printf("dp结果=%lld\n",dp[m][0]);
            //printf("分子=%lld\n",nu);
            //printf("分母=%lld\n",de);
            //printf("gcd=%lld\n",tmp);
            if(nu/tmp==0)
                printf("0\n");
            else if(nu/tmp==de/tmp)
                printf("1\n");
            else
                printf("%lld/%lld\n",nu/tmp , de/tmp);
        }
        return 0;
    }
  • 相关阅读:
    Chapter 03Using SingleRow Functions to Customize Output(03)
    Chapter 03Using SingleRow Functions to Customize Output(01)
    Chapter 04Using Conversion Functions and Conditional ExpressionsNesting Functions
    Chapter 04Using Conversion Functions and Conditional ExpressionsGeneral Functions
    Chapter 11Creating Other Schema Objects Index
    传奇程序员John Carmack 访谈实录 (zz.is2120)
    保持简单纪念丹尼斯里奇(Dennis Ritchie) (zz.is2120.BG57IV3)
    王江民:传奇一生 (zz.is2120)
    2011台湾游日月潭
    2011台湾游星云大师的佛光寺
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2833054.html
Copyright © 2011-2022 走看看