1. 程式人生 > >BZOJ 3029 守衛者的挑戰【概率DP】

BZOJ 3029 守衛者的挑戰【概率DP】

f [ i ] [ j ] [ k ]

f[i][j][k] 表示在前 i i 場挑戰中,贏下了 j j 場,揹包容量還剩下 k
k
的概率。

若第 i i 場輸掉,則:
f [ i ]

[ j ] [ k ] + = f [ i 1 ] [ j ] [ k ] ( 1 p [ i ] ) f[i][j][k]+=f[i-1][j][k]*(1-p[i])

否則:
f [ i ] [ j ] [ k ] + = f [ i 1 ] [ j 1 ] [ k a [ i ] ] p [ i ] f[i][j][k]+=f[i-1][j-1][k-a[i]]*p[i]

a n s = i = l n j = 0 n f [ n ] [ i ] [ j ] ans=\sum_{i=l}^n\sum_{j=0}^nf[n][i][j]

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define db double
#define sg string
#define ll long long
#define f(i,j,k) f[i][j][k+200] 
#define rep(i,x,y) for(ll i=(x);i<=(y);i++)
#define red(i,x,y) for(ll i=(x);i>=(y);i--)
using namespace std;

const ll N=2e2+5;
const ll Inf=1e18;

ll n,m,t,a[N];
db p[N],f[N][N][N<<1];

int main() {
	scanf("%lld%lld%lld",&n,&m,&t);
	
	f(0,0,min(t,n))=1;
	
	rep(i,1,n) scanf("%lf",&p[i]),p[i]/=100.0;
	
	rep(i,1,n) scanf("%lld",&a[i]);
	
	rep(i,0,n) rep(j,0,n) rep(k,-n,n) {
		if(a[i+1]==-1) {
			f(i+1,j,k)+=f(i,j,k)*(1.0-p[i+1]);
			f(i+1,j+1,k-1)+=f(i,j,k)*p[i+1];
		} else {
			f(i+1,j,k)+=f(i,j,k)*(1.0-p[i+1]);
			f(i+1,j+1,min(k+a[i+1],n))+=f(i,j,k)*p[i+1];
		}
	}
	
	db ans=0.0;
	
	rep(i,m,n) rep(j,0,n) ans+=f(n,i,j);
	
	printf("%.6lf",ans);

	return 0;
}