首页 > 代码库 > bzoj4008 [HNOI2015]亚瑟王

bzoj4008 [HNOI2015]亚瑟王

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4008

【题解】

我们把牌看成人吧好说明qwq

f[i,j]表示第i个人得到了j次机会的概率。

f[i,j]=f[i-1,j]*(1-p[i-1])^j+f[i-1,j+1]*(1-(1-p[i-1])^(j+1))

(前一个人得到了j次机会,都没有把握住;前一个人得到了j+1次机会,把握住了一次)

明显可以dp。

统计答案的话,就是

ΣΣf[i,j]*(1-(1-p[i])^j)*d[i]

(考虑每个人得到机会的概率,他们只要一次把握住就能造成伤害)

技术分享
# include <stdio.h>
# include <string.h>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 310;

# define RG register
# define ST static

int n, r;
ld p[M], d[M];
ld g[M][M], f[M][M]; 

int main() {
    int T; scanf("%d", &T);
    while(T--) {
        memset(f, 0, sizeof f); 
        scanf("%d%d", &n, &r);
        p[0] = 0.0; 
        for (int i=1; i<=n; ++i) {
            double pd, pe; scanf("%lf%lf", &pd, &pe);
            p[i] = (ld)pd; d[i] = (ld)pe; 
        }
        for (int i=0; i<=n; ++i) {
            g[i][0] = 1.0; 
            for (int j=1; j<=r; ++j)
                g[i][j] = g[i][j-1]*(1.0-p[i]);
        }
        // 第i个人得到了j次机会 
        ld ans = 0.0; 
        f[0][r] = 1.0; 
        for (int i=1; i<=n; ++i) 
            for (int j=1; j<=r; ++j) { 
                f[i][j] = f[i-1][j]*g[i-1][j] + f[i-1][j+1]*(1.0-g[i-1][j+1]);     
                ans = ans + f[i][j]*(1-g[i][j])*(ld)d[i];
            }
        printf("%.10lf\n", (double)ans);
    }
    return 0;
}
View Code

 

bzoj4008 [HNOI2015]亚瑟王