卧薪尝胆,厚积薄发。
POETIZE1 守卫者的挑战
Date: Tue Sep 04 14:37:54 CST 2018
In Category:
NoCategory
Description:
$N$
项挑战,如果
$a_i\ge0$
,挑战成功后可以获得一个容量为
$a_i$
的包;如果
$a_i=-1$
,挑战成功后可以得到一个物品,必须至少要成功
$L$
次。已知每项挑战成功的概率,求能把得到的物品装进包中的概率。
$1\le n \le 200$
Solution:
设
$f[i][j][k]$
表示到了第
$i$
场比赛,已经赢了
$j$
场,还有
$k$
的容量的概率,转移为
$f[i][j][k]\times(1-p_i)\to f[i+1][j][k]$
和
$f[i][j][k]\times p_i\to f[i + 1][j + 1][k +a[i]]$
。
$k$
可能很大,但物品大小只有一,所以
$\ge n$
的状态其实是一样的,
$i$
要滚动。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n,m,k;
#define MAXN 210
double f[2][MAXN][MAXN << 1];
double p[MAXN];
int a[MAXN];
int main()
{
scanf("%d%d%d",&n,&m,&k);
f[0][0][k + MAXN] = 1;
for(int i = 1;i <= n;++i)scanf("%lf",&p[i]);
for(int i = 1;i <= n;++i)scanf("%d",&a[i]);
int cur = 0;
for(int i = 1;i <= n;++i)
{
cur = cur ^ 1;
for(int l = 0;l <= n;++l)
for(int s = -n;s <= n;++s)
f[cur][l][s + MAXN] = 0;
for(int l = 0;l <= n;++l)
{
for(int s = -n;s <= n;++s)
{
if(s + a[i] >= n)f[cur][l + 1][n + MAXN] += f[cur ^ 1][l][s + MAXN] * p[i] / (double)100;
else f[cur][l + 1][s + a[i] + MAXN] += f[cur ^ 1][l][s + MAXN] * p[i] / (double)100;
f[cur][l][s + MAXN] += f[cur ^ 1][l][s + MAXN] * (100 - p[i]) / (double)100;
}
}
}
double ans = 0;
for(int l = m;l <= n;++l)
{
for(int s = 0;s <= n;++s)
{
ans += f[cur][l][s + MAXN];
}
}
printf("%.6lf\n",ans);
return 0;
}
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡