给出银行数n,和被抓到的概率P,在已知每个银行被抓的概率下,求在不被抓到的情况下,他最多能够抢多少钱。
求最优问题,看样例第一想到的就是动态规划的01背包,就去找了模板。
dp[j] 代表抢劫到 j元钱不被抓的概率,dp[j] = max( dp[j], dp[j - b[i].m] )* b[i].p),再和P判断即可,详见代码。
那个排序操作可有可无,一开始dp大小只开了105,一直RE,后来才反应过来dp大小是total_sum大小,就是一万,改了就对了。
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+5;
struct bank{
int m;
double p;
}b[105];
bool cmp1(bank a,bank b){
if(a.p==b.p)
return a.m>b.m;
return a.p<b.p;
}
double dp[N];
int main(){
int T,t=1;scanf("%d",&T);
while(T--){
double P;
int n,total_m=0;
scanf("%lf %d",&P,&n);
for(int i=0;i<n;i++){
scanf("%d %lf",&b[i].m,&b[i].p);
b[i].p=1-b[i].p;
total_m+=b[i].m;
}
sort(b,b+n,cmp1);
// memset(dp,0,sizeof(dp));
for(int i=0;i<=total_m;i++) dp[i]=0;
dp[0]=1;
for(int i=0;i<n;i++){
for(int j=total_m;j>=b[i].m;j--)
dp[j]=max(dp[j],dp[j-b[i].m]*b[i].p); //不被抓概率
}
// for(int i=0;i<n;i++)
// printf("%lf ",dp[i]);
int i;
for(i=total_m;i>=0;i--)
if(1-dp[i]<=P)
break;
printf("Case %d: %d\n",t++,i);
}
return 0;
}