hdu 2955 Robberies(01背包)

题意: 题目大意:有一个小偷要偷银行的钱,可是他偷没家银行总是有一定的概率被抓,现在给了你一个概率P,只要他被抓的概率乘积不大与P,他就是安全的。问你在他安全的情况下,他最多可以偷多少钱。

思路:还是和大多数人一样第一次想错了。吧概率当作背包,原本以为只需要扩大100倍概率将其变成整数就行了,然后发现有精度误差,有选择了long double发现交上去还是wa了。无奈,看了题解原来是将钱的总数看成背包,概率看成价值。
dp[i]表示可以安全逃脱的概率。
dp[j] 表示获得金额 j 时的安全概率。这里用滚动数组,得方程 dp[j] = max(dp[j], dp[i-a[i]]*(1-b[i]) 其中a表示银行金额,b表示被抓概率。

#include <iostream>
#include  <cstdio>
#include  <cstring>
#include <algorithm>
#define eps 1e-8
using namespace std;
const int maxn = 10005;
double dp[maxn], p, v[maxn];
int n, t, val[maxn], sum;
int main() {
    scanf("%d", &t);
    while(t--) {
        sum = 0;
        memset(dp, 0, sizeof(dp));
        cin >> p >> n;
        for(int i = 1; i <= n; i++) {
            cin >> val[i] >> v[i];
            sum += val[i];
        }
        dp[0] = 1.0; //dp表示安全概率
        for(int i = 1; i <= n; i++) {
            for(int j = sum; j >= val[i]; j--) {
                dp[j] = max(dp[j], dp[j - val[i]] * (1.0 - v[i]));
            }
        }
        int i;
        for( i = sum; i >= 0; i--) {
            if(dp[i] - (1 - p) > eps) break;
        }
        printf("%d\n", i);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/80390470
今日推荐