题目描述
打开了黑魔法师Vani的大门,队员们在迷宫般的路上漫无目的地搜寻着关押applepi的监狱的所在地。突然,眼前一道亮光闪过。“我,Nizem,是黑魔法圣殿的守卫者。如果你能通过我的挑战,那么你可以带走黑魔法圣殿的地图……”瞬间,队员们被传送到了一个擂台上,最初身边有一个容量为K的包包。
擂台赛一共有N项挑战,各项挑战依次进行。第i项挑战有一个属性ai,如果ai>=0,表示这次挑战成功后可以再获得一个容量为ai的包包;如果ai=-1,则表示这次挑战成功后可以得到一个大小为1 的地图残片。地图残片必须装在包包里才能带出擂台,包包没有必要全部装满,但是队员们必须把 【获得的所有的】地图残片都带走(没有得到的不用考虑,只需要完成所有N项挑战后背包容量足够容纳地图残片即可),才能拼出完整的地图。并且他们至少要挑战成功L次才能离开擂台。
队员们一筹莫展之时,善良的守卫者Nizem帮忙预估出了每项挑战成功的概率,其中第i项挑战成功的概率为pi%。现在,请你帮忙预测一下,队员们能够带上他们获得的地图残片离开擂台的概率。
题目大意
有 个挑战,每一个挑战成功后可以赢得一份数 ,求在赢得至少 场的情况下赢得的 .这样称之为成功,在给定每一个挑战成功的基础下求解最后成功的概率。
题解
做完这道题以后对概率有了一份更加深入的理解。我们队概率可以这样理解,对于每一个转移的状态看作是一份树形的结构,树的根节点的概率为1,接下来每一个节点的概率都均分这一个1的概率。而且每一份节点的概率为转移到这一个节点的概率之和而不是相乘。
捋顺概率的意义以后我们就可以来解决这一道题。
我们设 表示到了第 个挑战,赢了 个碎片,背包容量为 的概率。
我们可以根据当前状态去扩展未来状态.
如果第
个挑战成功了,
如果第
个挑战失败了,
然后你会发现 特别大,但是挑战只有 个,因此当容量超过 个的时候我们可以将容量设置为 ;且 最大的枚举量也为 。正确性可以保证,因为答案只是累加的并没有单独的作用,因为累加到 上不存在任何问题。
还有一个坑就是背包容量可以是负数,需要加上偏移量。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int N,L,R,K;
int a[300];
double p[300];
double f[205][205][500];
inline int F(int x)
{
if (x>N) x = N;
return x+205;
}
int main(void)
{
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
cin>>N>>L>>K;
for (int i=1;i<=N;++i)
{
int x;
cin>>x;
p[i] = x/100.0;
}
for (int i=1;i<=N;++i) cin>>a[i];
f[0][0][F(K)] = 1;
for (int i=0;i<N;++i)
for (int j=0;j<=i;++j)
for (int k=-N;k<=N;++k)
f[i+1][j+1][F(k+a[i+1])] += f[i][j][F(k)]*p[i+1],
f[i+1][j][F(k)] += f[i][j][F(k)]*(1-p[i+1]);
double ans = 0.0;
for (int j=L;j<=N;++j)
for (int k=0;k<=N;++k)
ans += f[N][j][F(k)];
printf("%.6lf",ans);
return 0;
}