劫匪 Roy 計劃搶劫 N 家銀行,每家有金額 Mj 和被抓概率 Pj。母親設定容忍總被抓概率 P。求在總被抓概率 < P 的前提下,最大期望搶劫金額。
關鍵轉化:獨立事件同時發生概率 = 概率乘積。
「不被抓概率」= 1 - 「被抓概率」。
目標:選擇子集使 ∏(1-Pj) > 1-P,最大化 ∑Mj。
dp[v] 表示搶到金額 v 時的最大「不被抓概率」dp[0] = 1(不搶任何銀行,安全概率 100%)dp[v] = max(dp[v], dp[v-Mj] * (1-Pj))dp[v] > 1-P 的 vN ≤ 100,Mj ≤ 100,總金額 ≤ 10000。
時間 O(N × 總金額) ≈ 10⁶,空間 O(總金額) ≈ 10⁴,極其高效。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define N 10005
int va[N];
double c[N], dp[N];
int main() {
int t, n, i;
double p;
scanf("%d", &t);
while (t--) {
int sum = 0;
scanf("%lf%d", &p, &n);
p = 1 - p; // 不被抓概率閾值
for (i = 0; i < n; i++) {
scanf("%d%lf", &va[i], &c[i]);
sum += va[i];
}
memset(dp, 0, sizeof(dp));
dp[0] = 1;
for (i = 0; i < n; i++)
for (int v = sum; v >= va[i]; v--)
dp[v] = max(dp[v], dp[v - va[i]] * (1 - c[i]));
for (i = sum; i >= 0; i--)
if (dp[i] - p > 1e-7) break;
printf("%d\n", i);
}
return 0;
}