题目大意
瞬间,队员们被传送到了一个擂台上,最初身边有一个容量为$K$的包包。
擂台赛一共有$N$项挑战,各项挑战依次进行。第$i$项挑战有一个属性,如果$a_i\ge 0$,表示这次挑战成功后可以再获得一个容量为的包包;如果$a_i=-1$,则表示这次挑战成功后可以得到一个大小为$1$的地图残片。地图残片必须装在包包里才能带出擂台,包包没有必要全部装满,但是队员们必须把获得的所有的地图残片都带走(没有得到的不用考虑,只需要完成所有项挑战后背包容量足够容纳地图残片即可),才能拼出完整的地图。并且他们至少要挑战成功L次才能离开擂台。
队员们一筹莫展之时,善良的守卫者Nizem帮忙预估出了每项挑战成功的概率,其中第$i$项挑战成功的概率为$\frac{p_i}{100}$。现在,请你帮忙预测一下,队员们能够带上他们获得的地图残片离开擂台的概率。
题目分析
一道比较简单的概率Dp。
设$f[i,j,k]$为前$i$项任务成功$j$个,当前背包容量为$k$的概率。
讨论一下任务是否成功即可。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| #include<algorithm> #include<iostream> #include<iomanip> #include<cstring> #include<cstdlib> #include<vector> #include<cstdio> #include<cmath> #include<queue> using namespace std; inline const int Get_Int() { int num=0,bj=1; char x=getchar(); while(x<'0'||x>'9') { if(x=='-')bj=-1; x=getchar(); } while(x>='0'&&x<='9') { num=num*10+x-'0'; x=getchar(); } return num*bj; } struct Challenge { double p; int v; bool operator < (const Challenge& b) const { return v>b.v; } } a[205]; int n,m,K; double f[205][205][205],ans=0; int main() { ios::sync_with_stdio(false); cin>>n>>m>>K; for(int i=1; i<=n; i++) { cin>>a[i].p; a[i].p/=100; } for(int i=1; i<=n; i++)cin>>a[i].v; sort(a+1,a+n+1); f[0][0][min(n,K)]=1; for(int i=0; i<n; i++) for(int j=0; j<=i; j++) for(int k=0; k<=n; k++) { f[i+1][j][k]+=f[i][j][k]*(1-a[i+1].p); int tmp=min(k+a[i+1].v,n); if(tmp<0)continue; f[i+1][j+1][tmp]+=f[i][j][k]*a[i+1].p; } for(int i=m; i<=n; i++) for(int j=0; j<=n; j++) ans+=f[n][i][j]; printf("%0.6lf\n",ans); return 0; }
|