本题关键在于注意到背包容量超过n以后是没有什么用的,视作n就好了。我是对于碎片局和背包局分开dp了。
dp1[i][j],对于碎片局,前i场赢j场的概率。
dp2[i][j][k],对于背包局,前i场赢j场,背包总容量>=k的概率
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 210
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,L,K,a2[N],p[N],n1=0,n2=0;
double dp1[N][N],p1[N],p2[N],dp2[N][N][N],ans=0;
//dp1[i][j],对于碎片局,前i场赢j场的概率。
//dp2[i][j][k],对于背包局,前i场赢j场,背包总容量>=k的概率
int main(){
// freopen("a.in","r",stdin);
n=read();L=read();K=read();K=min(K,n);
for(int i=1;i<=n;++i) p[i]=read();
for(int i=1;i<=n;++i){
int x=read();if(x==-1) p1[++n1]=p[i]*0.01;
else a2[++n2]=x,p2[n2]=p[i]*0.01;
}dp1[0][0]=1;
for(int i=1;i<=n1;++i)
for(int j=0;j<=i;++j){
dp1[i][j]=dp1[i-1][j]*(1-p1[i]);
if(j>0) dp1[i][j]+=dp1[i-1][j-1]*p1[i];
}
for(int k=0;k<=K;++k) dp2[0][0][k]=1;
for(int i=1;i<=n2;++i)
for(int j=0;j<=i;++j)
for(int k=0;k<=n;++k){
dp2[i][j][k]=dp2[i-1][j][k]*(1-p2[i]);
if(j>0) dp2[i][j][k]+=dp2[i-1][j-1][max(k-a2[i],0)]*p2[i];
}
for(int i=0;i<=n1;++i)
for(int j=max(L-i,0);j<=n2;++j)
ans+=dp1[n1][i]*dp2[n2][j][i];
printf("%.6lf\n",ans);
return 0;
}