加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

hdu 3076 ssworld VS DDD(概率DP)

发布时间:2020-12-14 04:33:06 所属栏目:百科 来源:网络整理
导读:题目描述 题面 题目大意:两个人A、B,血量分别为HA、HB,轮流掷骰子,每个人掷骰子的6种情况都有一定的概率,谁点数小谁扣一滴血,没血了就输了,问A赢的概率。 坑点:血量输入是反的,而且听说总概率还可能不等于1。-_-|| 题解 dp[i][j]表示A有i血,B有j血

题目描述

题面

题目大意:两个人A、B,血量分别为HA、HB,轮流掷骰子,每个人掷骰子的6种情况都有一定的概率,谁点数小谁扣一滴血,没血了就输了,问A赢的概率。

坑点:血量输入是反的,而且听说总概率还可能不等于1。-_-||


题解

dp[i][j]表示A有i血,B有j血A赢的概率。概率正推,dp[x][0]=1.0(x!=0),然后dp[i][j]=dp[i][j-1]*p1+dp[i-1][j]*p2,其中p1为每次A赢的概率,p2位每次B赢的概率。

注意平局不贡献答案,我们要预先处理出正确的p1和p2,忽略平局的影响。(说个类比,就是生物上的某基因型致死然后问你某个生物是某个基因型的概率)

然后由于double有爆空间的风险,直接滚动第一维即可。但是我想到一个问题,这样赋初值时让dp[0][0]=dp[1][0]=1.0,当i和j都为0时的状态的值不就错了吗?但是我们枚举状态时根本不会去算i=0或j=0的情况,所以根本没有这个转移,总之zenzen没问题。


代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>

using namespace std;

int n,m;
double dp[2][2002],a[7],b[7];

int main(){

    while(~ scanf("%d%d",&m,&n)){

        for(int i = 1; i <= 6; i++)  scanf("%lf",&a[i]);

        for(int i = 1; i <= 6; i++)  scanf("%lf",&b[i]);

        double p1 = 0.0,p2 = 0.0,sum;

        for(int i = 0; i <= m; i++)
            dp[0][i] = dp[1][i] = 0.0;

        for(int i = 1; i <= 6; i++)
            for(int j = 1; j <= 6; j++){
                if(i > j)  p1 += a[i] * b[j];
                if(i < j)  p2 += a[i] * b[j];
            }

        sum = p1 + p2;
        p1 /= sum;
        p2 /= sum;

        int x = 0;
        dp[0][0] = dp[1][0] = 1.0;

        for(int i = 1; i <= n; i++){
            x ^= 1;
            for(int j = 1; j <= m; j++)
            dp[x][j] = dp[x][j-1] * p1 + dp[x^1][j] * p2;
        }

        printf("%.6lfn",dp[x][m]);
    }

    return 0;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读