每日一题之 hdu2955 Robberies

Input
The first line of input gives T, the number of cases. For each scenario, the first line of input gives a floating point number P, the probability Roy needs to be below, and an integer N, the number of banks he has plans for. Then follow N lines, where line j gives an integer Mj and a floating point number Pj .
Bank j contains Mj millions, and the probability of getting caught from robbing it is Pj .

Output
For each test case, output a line with the maximum number of millions he can expect to get while the probability of getting caught is less than the limit set.

Notes and Constraints
0 < T <= 100
0.0 <= P <= 1.0
0 < N <= 100
0 < Mj <= 100
0.0 <= Pj <= 1.0
A bank goes bankrupt if it is robbed, and you may assume that all probabilities are independent as the police have very low funds.

Sample Input
3
0.04 3
1 0.02
2 0.03
3 0.05
0.06 3
2 0.03
2 0.03
3 0.05
0.10 3
1 0.03
2 0.02
3 0.05

Sample Output
2
4
6

题意:

给出几组数据,每组数据第一行是总被抓概率P(最后求得的总概率必须小于他,否则被抓),然后是想抢的银行数n。然后n行,每行分别是该银行能抢的钱数m[i]和被抓的概率p[i],求在不被抓的情况下最多能抢多少钱?

思路:

直接套01背包的框架的话,将概率看成背包的容量,进行dp,这样马上就会有一个问题了,概率是浮点数,根本能用枚举的方法去递推。所以要换个思路。我们把所有n个银行所有的钱看做是背包的容量,不被抓的概率看成价值,那么 dp[j] 的意义就变成了,抢到 j million的钱的时候且不被抓的概率。并且应该让不被抓的概率越大越好。状态转移方程为:
d p [ j ] = m a x ( d p [ j ] , d p [ j m [ i ] ] ) ( 1 p [ i ] ) 最后从后往前遍历dp数组,找到第一个大于 (1 - P)的 j ,j 就是答案。

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int maxn = 1e5+5;



int main()
{   

    int t;
    cin >> t;
    double p[maxn];
    int m[maxn];
    double dp[maxn+5];
    while(t--) {
        double P;
        int n;
        cin >> P >> n;
        int sum = 0;
        memset(m,0,sizeof(m));
        memset(p,0,sizeof(p));
        for (int i = 0; i < n; ++i) {
            cin >> m[i] >> p[i];
            sum += m[i];
        }
        memset(dp,0,sizeof(dp));
        dp[0] = 1;
        for (int i = 0; i < n; ++i) {
            for (int j = sum; j >= 0; --j) {
                if (j >= m[i])
                    dp[j] = max(dp[j],dp[j-m[i]]*(1-p[i]));
            }
        }
        for (int i = sum; i >= 0; --i) {
            if (dp[i] > (1.0-P) ) {
                cout << i << endl;
                break;
            }
        }
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/u014046022/article/details/80739050