hdu 3076 ssworld VS DDD(概率DP)

题目描述

题面

题目大意:两个人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("%.6lf\n", dp[x][m]);
    }

    return 0;
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值