题意分析:Roy要去偷银行的钱,每个银行都存在被抓住的概率。他麻麻担心他被抓,所以如果他抢劫的银行被抓住的概率大于P,她麻麻就不放心了。所以,我们要做的事情就是在小于妈妈担心概率的情况下,帮助Roy拿尽可能多的钱$$ :D
解题思路:钱和概率,很容易想到01背包问题。问题是,人家01背包给的都是整数,这里的概率是浮点数,循环都循环得蛋疼呀。。。。于是乎,想想问题能不能变成钱和概率的搭配,于是我们有: dp[i] 表示:拿到i的钱不被抓住的最大概率。(这里使用不被抓住的概率是因为,这样可以概率相乘直接得到。而被抓的概率是= 1- 不被抓的概率。显然,直接相乘方便些。)于是有 dp[i] = max(dp[i], dp[i - money[j]] * p[j])。问题得解~
具体代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 110;
int t, n;
int money[MAXN];
float p[MAXN];
float dp[10005]; //dp[i]:拿到i的钱,不被抓到的最大概率
int main() {
ios_base::sync_with_stdio(0);
float P;
cin >> t;
while (t --)
{
cin >> P >> n;
int sum = 0;
for (int i = 0; i < n; ++i)
{
cin >> money[i] >> p[i];
p[i] = 1 - p[i]; //不被抓住的概率
sum += money[i]; //总金钱数
}
memset(dp, 0, sizeof(dp));
dp[0] = 1.0;
for (int i = 0; i < n; ++i)
for (int j = sum; j >= money[i]; --j)
dp[j] = max(dp[j], dp[j - money[i]] * p[i]);
for (int i = sum; i >= 0; i--) //从高往后数,头一个不被抓概率大于麻麻期望概率的就是要的答案了~
if (dp[i] > 1.0 - P)
{
cout << i << '\n'; break;
}
}
return 0;
}