01背包问题
关键方程 f[j]=max{f[j],f[j-M[i]]*(1-P[i])}
把银行所有的钱看做背包,如果银行的钱少了,说明该盗贼没有被抓到,必须取没有被抓到的概率来进行相乘,
而不是用总的概率来减去下面各个不被抓到的分概率(这么做非常愚蠢,虽然我之前也这么想过)
然后从最大的总钱数开始遍历到0,取大于不被抓到的总概率,此时即得到了最大的可以抢劫到钱数
代码如下:
#include<stdio.h>
#include<string.h>
int M[110]; //钱数
double P[110],f[10010]; //概率,和最大的总钱数dp数组
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
double p;
int n,i,j,sum=0;
scanf("%lf%d",&p,&n);
p=1-p;
for(i=1;i<=n;i++)
{
scanf("%d%lf",M+i,P+i);
sum+=M[i];
}
memset(f,0,sizeof(f));
f[0]=1;
for(i=1;i<=n;i++)
for(j=sum;j>=M[i];j--)
f[j]=f[j]>(f[j-M[i]]*(1-P[i]))?f[j]:(f[j-M[i]]*(1-P[i])); //取最大的概率赋给f[j]
for(j=sum;j>=0;j--) //从最大钱数开始向前遍历,取第一个大于不被抓到的概率,即为最大钱数
if(f[j]>=p)
{
printf("%d\n",j);
break;
}
}
return 0;
}