题目大意: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;
}