Robberies---hdu2955(概率dp,01背包)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2955

题目给了每个银行的钱和被抓的概率,由于要抢尽量多的钱,所以要保证尽量不被抓,而抢多个银行之后不被抓的概率是抢每一个银行不被抓的概率之 积,dp[]表示抢到下标所对应的钱时,此时不被抓的概率,题目给出了最终不能高于被抓概率 P,不被抓的概率就不能低于(1-P),所以最后只需要逆序遍历dp,找到第一个大于等于1-P的dp[i],就能够保证i最大,即抢到的钱最多。

dp[j]=max(dp[j], dp[j-v[i]]*p[i]);

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
#define N 110
#define met(a, b) memset(a, b, sizeof(a))

double dp[N*N], p[N], P;
///dp[i]表示抢到价值为i,此时不被抓的概率,

int n, v[N];

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        met(v, 0); met(p, 0); met(dp, 0);

        scanf("%lf %d", &P, &n);
        int sum = 0;
        for(int i=1; i<=n; i++)
        {
            scanf("%d %lf", &v[i], &p[i]);
            p[i]=1-p[i];///p[i]表示抢第i个银行,不被抓的概率;
            sum+=v[i];
        }
        dp[0]=1;///没抢的时候肯定没被抓,概率为1;
        for(int i=1; i<=n; i++)
        {
            for(int j=sum; j>=v[i]; j--)
            {
                dp[j]=max(dp[j], dp[j-v[i]]*p[i]);
            }
        }
        for(int i=sum; i>=0; i--)
        {
            if(dp[i]>1-P)
            {
                printf("%d
", i);
                break;
            }
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zhengguiping--9876/p/4994685.html