3022
Problem V
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 29 Accepted Submission(s) : 11
3 0.04 3 1 0.02 2 0.03 3 0.05 0.06 3 2 0.03 2 0.03 3 0.05 0.10 3 1 0.03 2 0.02 3 0.05
2 4 6
Roy想要抢劫银行,给出每个银行所能抢到的钱数和被抓到的概率,求在不被抓到的情况下,最多能抢多少
思路:
1.抢劫N个银行不被抓,是每次都不被抓,所以概率应该是每次不被抓的概率相乘;
2.将所有银行所能抢到的总钱数化归为背包的总容量,但需要注意的是,在普通的0-1背包中的相加要改为相乘;
3.dp[j]=max(dp[j],dp[j-bank[i].money]*bank[i].run
AC:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
struct node
{
int money;
double run; //不被抓的概率
}bank[105];
double dp[105*105]; //数组的大小 开成105会RE
int main()
{
double t,p;
int T,i,n,j,maxmoney;
scanf("%d",&T);
while(T--)
{
maxmoney=0;
scanf("%lf %d",&p,&n);
p=1.0-p; //最大被抓概率转化为最小不被抓概率
for(i=1;i<=n;i++)
{
scanf("%d %lf",&bank[i].money,&t);
bank[i].run=1.0-t; //转化为不被抓的概率
maxmoney+=bank[i].money;
}
memset(dp,0,sizeof(dp)); //初始化为0不是-1
dp[0]=1.0; //不抢钱被抓概率为0
for(i=1;i<=n;i++) //抢i银行的钱
{
for(j=maxmoney;j>=bank[i].money;j--)
dp[j]=max(dp[j-bank[i].money]*bank[i].run,dp[j]);
}
for(i=maxmoney;i>=0;i--) //从最大钱数开始枚举
{
if(dp[i]>p)
{
printf("%d\n",i);
break;
}
}
}
return 0;
}