【BZOJ4008】[HNOI2015]亚瑟王(动态规划)

【BZOJ4008】[HNOI2015]亚瑟王(动态规划)

题面

BZOJ
洛谷

题解

\(f[i][j]\)表示前\(i\)张卡中有\(j\)张被触发的概率。
分两种情况转移,即当前这张是否被触发。
不被触发的概率是\(\displaystyle (1-p[i])^{r-j}\),即一共会考虑\(r-j\)次,每次都不被触发。
被触发的概率呢?拿不被触发的概率减一下就好了也就是\(1-(1-p[i])^{r-j+1}\)
所以得到转移:\(\displaystyle f[i][j]=f[i-1][j]*(1-p[i])^{r-j}+f[i-1][j-1]*(1-(1-p[i])^{r-j+1})\)
这样是概率,考虑怎么算期望,显然期望当且仅当一张卡被选择到的时候才会计算,那么额外开一个数组\(g[i][j]\),含义同\(f\),改概率为期望,转移的时候额外考虑一下期望的转移就好了。

#include<iostream>
#include<cstdio>
using namespace std;
double f[222][135],g[222][135],p[222],pw[222][135];
int n,r,d[222];
int main()
{
	int T;scanf("%d",&T);f[0][0]=1;
	while(T--)
	{
		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,f[i][0]=g[i][0]=0;
		for(int i=1;i<=n;++i)
			for(int j=1;j<=r;++j)
				f[i][j]=g[i][j]=0,pw[i][j]=pw[i][j-1]*(1-p[i]);
		for(int i=1;i<=n;++i)
			for(int j=0;j<=r&&j<=i;++j)
			{
				f[i][j]+=f[i-1][j]*pw[i][r-j],g[i][j]+=g[i-1][j]*pw[i][r-j];
				if(j)f[i][j]+=f[i-1][j-1]*(1-pw[i][r-j+1]),g[i][j]+=(g[i-1][j-1]+d[i]*f[i-1][j-1])*(1-pw[i][r-j+1]);
			}
		double ans=0;for(int i=0;i<=r;++i)ans+=g[n][i];
		printf("%.10lf\n",ans);
	}
	return 0;
}
posted @ 2019-01-06 17:29  小蒟蒻yyb  阅读(232)  评论(0编辑  收藏  举报