【文文殿下】[BZOJ4008] [HNOI2015] 亚瑟王

题解

这是一个经典的概率DP模型

(f_{i,j})表示考虑到前(i)张牌,有(j)轮没打出牌的可能性,那么显然(f_{0,r} = 1)

考虑第(i+1)张牌,他可能在剩下的(J)轮里打出,也可能都打不出。那么显然有两种转移。

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

在进行第二种转移的时候,我们把添加的值乘上他的伤害累加进答案

#include<cstdio>
#include<cstring>
const int maxn = 225;
double pw[maxn][maxn];
double ans,p[maxn];
double f[maxn][maxn];
int T,n,r,d[maxn];
inline void prelude() {
	scanf("%d%d",&n,&r);
	for(int i = 1;i<=n;++i) scanf("%lf%d",p+i,d+i);
	for(int i = 1;i<=n;++i) pw[i][0]=1;
	for(int i = 1;i<=n;++i) {
		for(int j = 1;j<=r;++j) {
			pw[i][j]=(1-p[i])*pw[i][j-1];
		}
	}
}
inline int solve() {
	ans = 0;
	memset(f,0,sizeof f);
	f[0][r]=1;
	for(int i = 0;i<n;++i) {
		for(int j = r;j;--j) {
			f[i+1][j]+=f[i][j]*pw[i+1][j];
			if(j>=1) {
				f[i+1][j-1]+=f[i][j]*(1-pw[i+1][j]);
				ans+=f[i][j]*(1-pw[i+1][j])*d[i+1];
			}
		}
	}
	printf("%.10lf
",ans);
}
int main() {
	scanf("%d",&T);
	while(T--){
		prelude();
		solve();
	}
	return 0;
}


原文地址:https://www.cnblogs.com/Syameimaru/p/10056638.html