【期望概率DP】守卫者的挑战

题意

\(N\)个数,依次选取,第\(i\)个数被选择的概率为\(p_i\),求至少选了\(L\)次后所选取的数的和\(+K\geq 0\)的概率。

思路

\(f_{i,j,k}\)为选到第\(i\)个数时已经选了\(j\)个,当前和为\(k\)时的概率。
考虑当前和\(\geq N\)时,可以将它视作为\(N\),因为它们都一定满足了选完之后\(\geq 0\)的条件,所以把它们归到\(N\)中,一起计算选不选择的概率即可。

代码

#include <cstdio>
#include <cstring>
#include <algorithm>

int n, l, K;
int w[201];
double ans;
double p[201], f[2][201][401];

int main() {
	scanf("%d %d %d", &n, &l, &K);
	for (int i = 1; i <= n; i++)
		scanf("%lf", &p[i]), p[i] /= 100;
	for (int i = 1; i <= n; i++)
		scanf("%d", &w[i]);
	if (K > n)
		K = n;
	f[0][0][K + 200] = 1;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j <= i; j++)
			for (int k = -i; k <= n; k++) {
				f[(i + 1) & 1][j + 1][std::min(k + w[i + 1], n) + 200] += f[i & 1][j][k + 200] * p[i + 1];
				f[(i + 1) & 1][j][k + 200] += f[i & 1][j][k + 200] * (1 - p[i + 1]);
			}
		memset(f[i & 1], 0, sizeof(f[i & 1]));
	}
	for (int i = l; i <= n; i++)
		for (int j = 0; j <= n; j++)
			ans += f[n & 1][i][j + 200];
	printf("%.6lf", ans);
}
posted @ 2021-03-27 16:34  nymph181  阅读(48)  评论(0)    收藏  举报