Robberies
Description
For a few months now, Roy has been assessing the security of various banks and the amount of cash they hold. He wants to make a calculated risk, and grab as much money as possible.
His mother, Ola, has decided upon a tolerable probability of getting caught. She feels that he is safe enough if the banks he robs together give a probability less than this.
Input
Bank j contains Mj millions, and the probability of getting caught from robbing it is Pj .
Output
Notes and Constraints
0 < T <= 100
0.0 <= P <= 1.0
0 < N <= 100
0 < Mj <= 100
0.0 <= Pj <= 1.0
A bank goes bankrupt if it is robbed, and you may assume that all probabilities are independent as the police have very low funds.
Sample 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
Sample Output
2
4
6
题意:一个强盗抢银行,每个银行都有一个 int 型存款和一个 float 型被抓的可能性,这个强盗想在被抓可能性不超过某个浮点型 K 的情况下尽可能多的抢钱,问最多能抢到多少钱?
思路:这个题在我以前做背包问题的时候做过,但是当时是将所有的浮点数放大100000倍,而且将被抓的概率直接相加,当成01背包来做。。。显而易见,WA的很惨。。。昨天开始刷动态规划46题,第一题就是这个题,问了一下暾哥,严重怀疑自己的智商。。。言归正传,我们这里将dp[ i ]作为抢到 i 元钱不被抓的概率, 然后将 n 个银行依次放入,假设第 i 个银行有钱 money[ i ] 元, 不被抓的可能性为 pos[ i ],那么我们放入第 i 个银行以后,用 j 代表我们抢的钱,从10000向前遍历,一直到money[ i ],状态转移方程为 dp[ j ] = max(dp[ j ] , pos[ i ]*dp[ j -money[ i ] ])
从后向前遍历是为了不重复,一个银行抢一次。做过背包的无需赘述。
下面贴一下代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int money[105];
double pos[105];
double dp[10005];
int main(){
int T;
scanf("%d",&T);
while(T--){
int n;
double total;
memset(dp,0,sizeof(dp));
scanf("%lf%d",&total,&n);
total = 1-total;
for(int i = 0; i < n; i++){
scanf("%d",&money[i]);
scanf("%lf",&pos[i]);
pos[i] = 1-pos[i];
}
dp[0] = 1;
for(int i = 0; i < n; i++){//!!放入的序号
for(int j = 10002; j >= money[i]; j--){
dp[j] = max(dp[j],pos[i]*dp[j-money[i]]);
}
}
for(int i = 10002; i >= 0; i--){
if(dp[i] >= total){
cout << i << endl;
break;
}
}
}
}