BAPC 2019 L-Lucky Draw 概率DP

題目鏈接:https://nanti.jisuanke.com/t/44330
題意:有n個人玩遊戲,每個人擁有k條生命。每輪每個人會有p的概率不會死,求最後是平局的概率
思路:設f[i][j]表示i輪後剩餘j條生命的概率,那麼 f[i][j] = p * f[i - 1][j] + (1 - p) * f[i - 1][j + 1]
由於生命都相同,P(平局) = 1 - P(某人贏) = 1 - n* P(第一個人贏) = 1 - n * sum( P(第一個人第i輪贏其餘人i-1輪死) ) 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define fi first
#define se second
#define ls rt << 1
#define rs rt << 1|1
#define lson l, mid, ls
#define rson mid + 1, r, rs
#define pll pair<ll, ll>
#define pii pair<int, int>
#define ull unsigned long long
#define pdd pair<double, double>
const int mod = 1e9 + 7;
const int maxn = 1e3 + 10;
const int inf = 0x3f3f3f3f;
double f[maxn][maxn]; //f[i][j]表示i輪後剩餘j條生命的概率

int main()
{
    int n, m;
    double p;
    scanf("%d%d%lf", &n, &m, &p);
    f[0][m] = 1;
    for(int i = 1; i < maxn; ++i)
    {
        for(int j = m; j > 0; --j)
            f[i][j] = p * f[i - 1][j] + (1 - p) * f[i - 1][j + 1];
        f[i][0] = f[i - 1][0] + (1 - p) * f[i - 1][1]; //生命耗盡時不用乘以p
    }
    double ans = 0;
    for(int i = 1; i < maxn; ++i) //1000次之後的概率對答案影響很小
    {
        ans += (f[i][0] - f[i - 1][0]) * pow(f[i - 1][0], n - 1); //計算在i輪死亡並且其他人都在i輪之前死亡的概率
    }
    printf("%.10f\n", 1 - n * ans);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章