题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=87125#problem/M
题意:
一个人想要抢劫银行,每家银行都有一定的金额和被抓到的概率,知道小偷被抓的最大概率P,求他在不被被抓的情况下,抢劫的钱最多是多少。
案例:
input
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
output
2
4
6
思路分析:
知道小偷在每个银行被抓的概率P[i],则可知小偷成功偷取的概率为1-P[i]。不需要打印,可以写成滚动数组。
当小偷偷的前为0时,小偷是完全安全的,而在偷取其它金额的开始都是成功率为0,所以要先清零,在给d[0]赋值为1。
可以对背包问题做一个简单转换,把银行总钱sum作为背包容量C,把(1-p[i])作为重量W,背包问题模版请参考紫书。
最后,倒叙,找出可以偷出的最多的钱。条件为>(1-P)。
源代码如下:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define MAX 10005 6 using namespace std; 7 int main() 8 { 9 int T,N,m[105]; 10 double P,p[105],d[MAX]; 11 scanf("%d",&T); 12 while(T--) 13 { 14 int sum=0,i,j; 15 scanf("%lf%d",&P,&N); 16 for(i=0;i<N;i++) 17 { 18 scanf("%d%lf",&m[i],&p[i]); 19 sum+=m[i]; 20 } 21 memset(d,0,sizeof(d)); //初始化 22 d[0]=1; 23 for(i=0;i<N;i++) 24 for(j=sum;j>=m[i];j--) 25 d[j]=max(d[j],d[j-m[i]]*(1-p[i])); //状态转移公式 26 for(i=sum;i>=0;i--) 27 if(d[i]>=(1-P)) //找出最多的钱 28 { 29 printf("%d\n",i); 30 break; 31 } 32 } 33 return 0; 34 }