不是一个背包问题。但是,问题经变化后与01背包思路上别无二致。
注意到不被逮捕的条件:1-(1-p1)(1-p2)(1-p3)...(1-pk)<p(其中p表示最大危险概率),不妨将问题转化,使dp[i][j]表示对于前i个银行,可取总金额为j时,最大的安全的概率;
那么dp[i][j]=max(dp[i-1][j],dp[i-1][j-m[i]]*p[i])(其中p[i]表示抢劫第i个银行的最大安全概率)
运用01 背包解出dp[i](运用了压缩空间的技巧,使二维变一维)后,注意到,随着i(表示可取金额)增大,dp[i]不减,那么显然,安全情况中最危险的情况对应的金额便是问题的最后答案。
这里给出一维写法:
#include<stdio.h> #include<algorithm> #include<string.h> using namespace std; double p[10005],dp[10005]; int m[105]; int vol;//all the money int main() { int t; scanf("%d",&t); while(t--) { memset(dp,0,sizeof(dp)); int n; double maxp; scanf("%lf%d",&maxp,&n); maxp=1-maxp; vol=0; for(int i=1;i<=n;i++) { scanf("%d%lf",&m[i],&p[i]); p[i]=1-p[i]; vol+=m[i]; } dp[0]=1;//improtant for(int i=1;i<=n;i++) { for(int v=vol;v>=m[i];v--) { dp[v]=max(dp[v],dp[v-m[i]]*p[i]); } } for(int maxm=vol;maxm>=0;maxm--) if(dp[maxm]>=maxp) { printf("%d\n",maxm); break; } } return 0; }