题目大意:harry要去抢劫银行,他手上有每个银行布局,所以他很清楚的了解到每个银行有多少钱,和去抢劫该银行被捕的概率
现在他要拟定一个计划,要求在被捕概率低于p的情况下,抢劫到最多的钱
解题思路:银行1个1个的抢过去,抢到的钱随着抢劫银行的数量增加或者不变(不变的情况就是不抢劫该银行),被捕的概率随着银行数量的增加而增大或者不变(不变的情况就是不抢劫该银行)
所以这个题有三个量在改变,一个是银行的数量,一个是抢到的钱,还有一个是被捕的概率
所以用二维dp来表示三个变量,设dp[i][j]表示抢劫了前i个银行,抢了j的钱被捕的概率
那么dp[i][j] = min(dp[i-1][j],dp[i-1][j-money[i]] + (dp[i-1][j-money]) * rob[i])
其中money[i]表示第i个银行的有多少钱,rob[i]表示抢劫第i个银行被捕的概率
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const double esp = 1e-7;
const int N = 110;
const int M = 10010;
int money[N], sum, n;
double rob[N],dp[N][M], p;
void solve() {
for(int i = 1; i <= sum; i++)
dp[0][i] = (double)-1;
dp[0][0] = 0;
for(int i = 1; i <= n; i++)
for(int j = 0; j <= sum; j++) {
dp[i][j] = dp[i-1][j];
if(j - money[i] >= 0 && fabs(dp[i-1][j-money[i]] + (double)1) > esp) {
if(fabs(dp[i][j] + (double)1) > esp)
dp[i][j] = min(dp[i][j], dp[i-1][j-money[i]] + (1 - dp[i-1][j-money[i]]) * rob[i]);
else
dp[i][j] = dp[i-1][j-money[i]] + (1 - dp[i-1][j-money[i]]) * rob[i];
}
}
}
int main() {
int test, cas = 1;
scanf("%d", &test);
while(test--) {
scanf("%lf%d", &p, &n);
sum = 0;
for(int i = 1; i <= n; i++) {
scanf("%d%lf", &money[i], &rob[i]);
sum += money[i];
}
solve();
for(int i = sum; i >= 0; i--) {
if(dp[n][i] >= 0.0 && p - dp[n][i] > esp) {
printf("Case %d: %d\n", cas++, i);
break;
}
}
}
return 0;
}