suxxsfe

一言(ヒトコト)

bzoj3029 守卫者的挑战

bzoj3029 守卫者的挑战

Description

打开了黑魔法师Vani的大门,队员们在迷宫般的路上漫无目的地搜寻着关押applepi的监狱的所在地。突然,眼前一道亮光闪过。“我,Nizem,是黑魔法圣殿的守卫者。如果你能通过我的挑战,那么你可以带走黑魔法圣殿的地图……”瞬间,队员们被传送到了一个擂台上,最初身边有一个容量为K的包包。

擂台赛一共有\(N\)项挑战,各项挑战依次进行。第\(i\)项挑战有一个属性\(a_i\),如果\(a_i\geq 0\),表示这次挑战成功后可以再获得一个容量为\(a_i\)的包包;如果\(a_i=-1\),则表示这次挑战成功后可以得到一个大小为1 的地图残片。地图残片必须装在包包里才能带出擂台,包包没有必要全部装满,但是队员们必须把 【获得的所有的】地图残片都带走(没有得到的不用考虑,只需要完成所有N项挑战后背包容量足够容纳地图残片即可),才能拼出完整的地图。并且他们至少要挑战成功L次才能离开擂台。

队员们一筹莫展之时,善良的守卫者Nizem帮忙预估出了每项挑战成功的概率,其中第i项挑战成功的概率为pi%。现在,请你帮忙预测一下,队员们能够带上他们获得的地图残片离开擂台的概率。

对于 100% 的数据,保证\(0\leq K\leq 2000,0\leq N \leq 200,-1 \leq a_i \leq 1000,0\leq L\leq N,0\leq p_i\leq 100\)


 
概率dp
状态设计:\(f_{i,j,k}\)表示考虑前\(i\)个比赛,赢了\(j\)个,目前剩余的背包容量为\(k\)的概率
其实\(a_i\)是否大于等于0的两种情况可以合并,就是剩余容量增加了\(a_i\)我还傻傻的取分类讨论\(a_i\)是不是大于等于0
转移即为:

  • 赢了比赛,\(f_{i,j+1,k+a_i}+=f_{i-1,j,k}\times p_i\)
  • 输了比赛,\(f_{i,j,k}+=f_{i-1,j,k}\times (1-p_i)\)

但是因为剩余空间可能很大,所以内存会炸
可以想到,由于\(n\leq 200\),所以多余200的容量是无意义的,那么可以每次都给\(k\)与200取\(\min\)
还有,再过程中\(k\)有可能小于0,之后再加成正的,因此,\(k\)再数组中的下标应该\(+200\),避免下标变成负数

最后的答案当然就是\(\sum_{j=l}^{n}\sum_{k=0}^{200} f_{n,j,k}\)

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#define reg register
#define EN std::puts("")
#define LL long long
inline int read(){
	int x=0,y=1;
	char c=std::getchar();
	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
	return y?x:-x;
}
int n,l,k;
double f[206][206][416];
double p[206];
inline int getit(int kk){
	return kk>200?200:kk;
}
int main(){
	n=read();l=read();k=read();
	for(reg int i=1;i<=n;i++) std::scanf("%lf",&p[i]),p[i]/=100;
	f[0][0][getit(k)+200]=1;
	reg int ai;
	for(reg int i=1;i<=n;i++){
		ai=read();
		for(reg int j=0;j<=i;j++){
			for(reg int kk=-200;kk<=200;kk++){
				f[i][j][kk+200]+=f[i-1][j][kk+200]*(1-p[i]);
				f[i][j+1][getit(kk+ai)+200]+=f[i-1][j][kk+200]*p[i];
			}
		}
	}
	reg double ans=0;
	for(reg int j=l;j<=n;j++){
		for(reg int kk=0;kk<=200;kk++) ans+=f[n][j][kk+200];
	}
	std::printf("%.6lf",ans);
	return 0;
}
posted @ 2020-03-19 21:19  suxxsfe  阅读(129)  评论(0编辑  收藏  举报