1. 程式人生 > >BZOJ #4832. 抵制克蘇恩

BZOJ #4832. 抵制克蘇恩

題意

場上有1血,2血,3血隨從,總數不超過7,外加一個英雄

每次克蘇恩會等概率攻擊一個人,若隨從被打一下還沒死,且場上隨從<7,那麼會有一個3血隨從

問英雄收到的傷害的期望值

題解

概率Dp,p[i][a][b][c]表示攻擊到第i次,場上有1血,2血,3血隨從分別a,b,c個的概率

f[i][a][b][c]表示攻擊到第i次,場上有1血,2血,3血隨從分別a,b,c個時英雄收到傷害的期望值

除錯記錄

判斷隨從是否<7時沒把a,b算上

#include <cstdio>
#include <cstring>
#include
<algorithm>
#define maxn 105 using namespace std; long double p[maxn][8][8][8], f[maxn][8][8][8]; int k, A, B, C, T; int main(){ scanf("%d", &T); while (T--){ scanf("%d%d%d%d", &k, &A, &B, &C); memset(f, 0, sizeof f); memset(p, 0, sizeof p); p[0][A][B][C] = 1.0; for
(int i = 0; i < k; i++){ for (int a = 0; a <= 7; a++){ for (int b = 0; a + b <= 7; b++){ for (int c = 0; a + b + c <= 7; c++){ long double P = (long double)1.0 / (a + b + c + 1); if (a != 0){ f[i + 1][a - 1][b][c] += f[i][a][b][c] * P * a; p[i + 1][a - 1][
b][c] += p[i][a][b][c] * P * a; } if (b != 0){ f[i + 1][a + 1][b - 1][min(a + b + c + 1, 7) - a - b] += f[i][a][b][c] * P * b; p[i + 1][a + 1][b - 1][min(a + b + c + 1, 7) - a - b] += p[i][a][b][c] * P * b; } if (c != 0){ f[i + 1][a][b + 1][min(a + b + c + 1, 7) - a - b - 1] += f[i][a][b][c] * P * c; p[i + 1][a][b + 1][min(a + b + c + 1, 7) - a - b - 1] += p[i][a][b][c] * P * c; } f[i + 1][a][b][c] += (f[i][a][b][c] + p[i][a][b][c]) * P; p[i + 1][a][b][c] += p[i][a][b][c] * P; } } } } long double ans = 0; for (int a = 0; a <= 7; a++) for (int b = 0; b <= 7; b++) for (int c = 0; c <= 7; c++) ans += f[k][a][b][c]; printf("%.2lf\n", (double)ans); } return 0; }