[HDU2955]Robberies[dp]

题目链接:[HDU2955]Robberies[dp]

题意分析: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;
}

你可能感兴趣的:(dp,HDU,概率)