• hdu3076—概率dp


    hdu3076—概率dp

    标签 : 概率dp


    题目链接

    • 题意:
      2个人分别有AB的血数,轮流扔骰子,数小的自减一血,平的不变,谁先到减0, 谁输,问A赢的概率。
    • 题解:
      dp[i][j]表示的是第一个人有i血,第二个人有j个血的时候1赢的概率。转移方程,假设p1是每一剧中第一个人赢的概率,p2是第二个人赢的概率,dp[i][j] 转化到dp[i-2][j]的概率是p2,dp[i][j]转化到dp[i][j-1]的概率是p1,那么 (dp[i][j] = d[i-1][j]*p2+dp[i][j-1]*p1;)
    • 注意事项:
      1. 因为是概率的问题,所以要考虑精度的问题,所以一般定义状态的时候就直接把dp[n][m]定义成最后的结果,不然如果最后的结果需要相加或者别的形式运算才能得到的话很有可能有精度的问题,刚开始定义dp[i][j]表示第一个人失去i格血,第二个人失去j格血的概率;
      2. 这个题一定是个脑残出的,m和n的输入是反的,而且输入并不保证输入的赢的概率和平的概率还有输的概率加起来等于1
      3. 这个题要注意要进行一次概率转化。通过概率转化排除平局的概率对答案的影响。
    • ac 代码和错误代码
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 2008;
    double dp[N][N];//dp[i][j]表示的是第一个人有i血,第二个人有j个血的时候1赢的概率。
    double a[6],b[6];
    int main()
    {
        int n, m;
        while(~scanf("%d%d",&m,&n))
        {
            for(int i = 0; i < 6; i++)  scanf("%lf",&a[i]);
            for(int j = 0; j < 6; j++)  scanf("%lf",&b[j]);
            double p1, p2, ping;
            p1 = p2 = ping = 0;
            
            for(int i = 0; i < 6; i++){
                for(int j = 0; j <= 6; j++){
                    //if(i==j) ping += a[i]*b[j];
                    if(i>j)
                        p1 += a[i]*b[j];
                    else if(i<j)
                        p2 +=a[i]*b[j];
                }
            }
           // p2 = 1-p1-ping;
            double tm = p1+p2;
            p1 = p1/tm;
            p2 = p2/tm;
            //printf("%lf %lf %lf
    ",p1,p2,ping);
            for(int i = 0; i <= m; i++) dp[0][i] = 0;
            for(int j = 0; j <= n; j++) dp[j][0] = 1;
            for(int i = 1; i <= n; i++){
                for(int j = 1; j <= m; j++){
                    dp[i][j] = dp[i-1][j]*p2+dp[i][j-1]*p1;
                }
            }
            printf("%lf
    ",dp[n][m]);
        }
        return 0;
    }
    
    
    
    
    
    
    
    
    /*
    
    //下面是错误的代码,因为想一下其实每次得到的不是最后的解,那么精度会有很大问题
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 2008;
    double dp[N][N];//dp[i][j]表示第一个人失去i格血,第二个人失去j格血的时候1赢的概率;
    double a[6],b[6];
    int main()
    {
        int n,m;
        while(~scanf("%d%d",&n,&m))
        {
            for(int i = 0; i < 6; i++) scanf("%lf",&a[i]);
            for(int i = 0; i < 6; i++) scanf("%lf",&b[i]);
            double p = 0;
            double p2 = 0;
            double ping = 0;
            for(int i = 0; i < 6; i++){
                for(int j = 0; j < i; j++){
                    if(i==j) ping = a[i]*b[j];
                    else
                        p += a[i]*b[j];
                }
            }
            p2 = 1-p-ping;
          //  printf("%lf %lf
    ",p,p2);
           // memset(dp,0,sizeof(dp));
           for(int i = 0;i <= n; i++){
                for(int j = 0; j <= m; j++)
                    dp[i][j] = 1;
           }
            dp[0][1] = p;
            dp[1][0] = p2;
            for(int i = 1; i <= n; i++){
                for(int j = 1; j <= m; j++){
                    dp[i][j] = dp[i-1][j]*p2+dp[i][j-1]*p;
                }
            }
            double ans = 0;
            for(int i = 0; i < n; i++){
                ans*=dp[i][m];
            }
            printf("%lf
    ",ans);
        }
        return 0;
    }
    */
    
    
  • 相关阅读:
    使用CustomValidate自定义验证控件
    C#中金额的大小写转换
    Andriod出错之Unable to build: the file dx.jar was not loaded from the SDK folder!
    VC 编写的打字练习
    机房工作笔记Ping只有单向通
    web服务协同学习笔记(1)
    Dll 学习3 将MDI子窗口封装在DLL中
    机房工作学习文件共享
    Andriod出错之Failed to find an AVD compatible with target 'Android 2.2'
    Andriod出错之wrapper was not properly loaded first
  • 原文地址:https://www.cnblogs.com/shanyr/p/5808231.html
Copyright © 2020-2023  润新知