http://acm.hdu.edu.cn/showproblem.php?pid=2955
题目大意:劫匪抢银行,要求被抓概率小于P。共有n个银行,第i个银行钱数为m[i],被抓概率为p[i](float型);求劫匪最多能抢多少钱;
思路:由于代价(被抓概率)是浮点型且不能直接相加,所以不能以代价为背包。这个题目可以以获得的价值(即抢到的钱数)为背包,求抢到一定钱时逃跑的概率;虽然抢到的钱数不是连续变化的,但是通过初始化时的巧妙处理还是可以连续遍历的,具体见代码及注释;
#include<stdio.h>
#include<string.h>
#define ans(a,b) ((a)>(b)?(a):(b))
#define N 111
int m[N];
float p[N],f[11111];
int main()
{
int T,n,i,j,sum,ans;
float P;
scanf("%d",&T);
while(T--){
sum=0,ans=0;
scanf("%f%d",&P,&n);
for(i=0;i<n;i++){
scanf("%d%f",&m[i],&p[i]);
sum+=m[i];
}
memset(f,0,sizeof(f));//初始化,特别注意f[0];
f[0]=1;
//计算抢j金钱时逃跑的概率
for(i=0;i<n;i++){
for(j=sum;j>=m[i];j--){//注意j的下限
f[j]=ans(f[j],f[j-m[i]]*(1-p[i]));
}
}
for(j=0;j<=sum;j++){//对于j取不到的值恒有f[j]=0,why?想想初始化
if(P>(1-f[j])&&j>ans)
ans=j;
}
printf("%d\n",ans);
}
return 0;
}