题目大意:
擂台赛有
个挑战,一开始有一个容量为
的包包,第
项挑战有一个属性
,如果
,表示这次挑战成功后可以再获得一个容量为
的包包。
,挑战成功后可以得到一个大小为
的地图残片。
队员们必须把获得的所有的地图残片都带走(没有得到的不用考虑,只需要完成所有
项挑战后背包容量足够容纳地图残片即可),才能拼出完整的地图。并且他们至少要挑战成功
次才能离开擂台。
给出每项挑战成功的概率,第
项挑战成功的概率为
。
请求出他们获得的地图残片离开擂台的概率。
分析:
因为不用考虑挑战的顺序,所以我们先考虑赢了不需要占用背包的情况,即优先赢了能获得背包容量的。
然后设
为前
场比赛,赢了
场,背包容量为
的概率
因为情况再坏也就
个地图碎片需要带走,所以
{
}
那么我们就可以不会炸内存了,然后对于
可以滚动一下
对于前
场而言,
第
场赢了,则
第
场输了,则
最后的答案就是
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define fo(i, j, k) for(i = j; i <= k; i++)
#define N 205
using namespace std;
struct Node { double p; int v; }a[N];
double f[2][N][N], ans;
int p[N], n, l, m;
int i, j, k;
bool cmp(Node aa, Node bb) {
return aa.v > bb.v;
}
int main() {
scanf("%d %d %d", &n, &l, &m);
fo(i, 1, n) scanf("%lf", &a[i].p);
fo(i, 1, n) scanf("%d", &a[i].v);
sort(a+1, a+n+1, cmp);
f[0][0][min(n,m)] = 1;
fo(i, 0, n-1) {
int br = i%2;
int dr = br^1;
fo(j, 0, i+1)
fo(k, 0, n) f[dr][j][k] = 0;
fo(j, 0, i)
fo(k, 0, n) {
if (k+a[i+1].v >= 0) f[dr][j+1][min(n,k+a[i+1].v)] += f[br][j][k]*(a[i+1].p/100);
f[dr][j][k] += f[br][j][k]*((100-a[i+1].p)/100);
}
}
fo(i, l, n)
fo(j, 0, n) ans += f[n%2][i][j];
printf("%.6lf", ans);
return 0;
}