开始就想到了用一个三维的f数组表示第i场,赢了几场,还剩下多少空间,但是发现空间的极限最大值是200000,在开一个三维的数组就爆内存了,后来想到用map实现动态开点,但是这样时间复杂度过不了,并且还表示不了赢了多少场的状态,后来参考了一下题解,发现当背包的空间加到大于n的时候,无论怎么样,背包空间的大小都不可能变为零,所以就可以把空间大于n的一起放到n上,以为在转移的时候,空间大小为负数依然合法,因为在后来可以通过扩大背包讲空间变为正的,处理的方法是将所有的空间大小都加上一个值,这要就能保证数组下标都是正的;
开始还理解错题意了,以为胜利L场,并且背包空间非负就可以结束挑战,卡了很长时间,审题的重要性
1 #include<map> 2 #include<cmath> 3 #include<ctime> 4 #include<vector> 5 #include<cstdio> 6 #include<cstdlib> 7 #include<cstring> 8 #include<iostream> 9 #include<algorithm> 10 using namespace std; 11 int n,L,K; 12 double p[210]; 13 int a[210]; 14 double f[201][201][410]; 15 int main(){ 16 //freopen("a.in","r",stdin); //freopen("sc2.out","w",stdout); 17 //freopen("guarda.in","r",stdin); freopen("guarda.out","w",stdout); 18 scanf("%d%d%d",&n,&L,&K); 19 for(int i=1;i<=n;i++) scanf("%lf",&p[i]),p[i]/=100; 20 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 21 if(a[1]==-1){ 22 f[1][1][K-1+205]=p[1]; 23 f[1][0][K+205]=(1-p[1]); 24 } 25 else{ 26 int cc=a[1]+K; 27 if(cc>n) cc=n; 28 f[1][1][cc+205]=p[1]; 29 f[1][0][K+205]=(1-p[1]); 30 } 31 int N=n+205; 32 for(int i=2;i<=n;i++){ 33 for(int j=0;j<=n;j++){ 34 for(int k=1;k<=409;k++){ 35 if( f[i-1][j][k]==0 ) continue; 36 if( a[i]==-1 ){ 37 f[i][j+1][k-1]+=f[i-1][j][k]*p[i]; 38 f[i][j][k]+=f[i-1][j][k]*(1-p[i]); 39 } 40 else{ 41 int d=a[i]+k; 42 if(d>N) d=N; 43 f[i][j+1][d]+=f[i-1][j][k]*p[i]; 44 f[i][j][k]+=f[i-1][j][k]*(1-p[i]); 45 46 } 47 } 48 } 49 } 50 double ans=0; 51 for(int j=L;j<=n;j++){ 52 for(int k=205;k<=409;k++){ 53 ans+=f[n][j][k]; 54 } 55 } 56 printf("%.6lf",ans); 57 return 0; 58 59 }