题目大意:
某人要抢劫银行,给出你一个最大被抓的概率p,和银行个数,随后给出每个银行的钱数和被抓的概率,要求在被抓概率小于p的情况下获得的最大的money。
题解:
妥妥的一道01背包,本来把被抓概率当成01背包中的体积了,只需要把所有概率都×100在处理就好了,后来发现不行,首先对于多个银行都去抢的话概率是相乘的,然后他给的概率不见得就是两位小数的,所以此路不通。
仔细想想01背包的内容,遍历一遍物品(再此题中为银行)是不能少的,然后需要一个取值为正整数的变量,好像只有钱数是正整数了,于是我们想着向这个方向转化。被抓概率小于p是必须的,那么我们可以转化为逃跑概率要大于1 - p,我们可以将钱数作为01背包中的体积V,把逃跑概率作为价值val,只需要找出逃跑概率 > p 的最大钱数就是答案
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int t, n;
double dp[12000];
int money[130];
double ex[130], p;
int main()
{
scanf("%d", &t);
while(t--)
{
scanf("%lf%d", &p, &n);
int sum = 0;
for(int i = 1; i <= n; ++ i)
{
scanf("%d%lf", &money[i], &ex[i]);
sum += money[i];
}
memset(dp, 0, sizeof(dp));
dp[0] = 1;
for(int i = 1; i <= n; ++ i)
{
for(int j = sum; j >= money[i]; --j)
{
dp[j] = max(dp[j], dp[j - money[i]] * (1 - ex[i]));
}
}
for(int i = sum; i >= 0; -- i)
{
if(1.0 - dp[i] < p)
{
cout << i << endl;
break;
}
}
}
return 0;
}