HDU 2955 Robberies 变形01背包

题意:Roy打算抢劫银行。有N个银行,每个银行有存款Mi,和被抢劫后抓住的概率Pi。不同银行被抓的概率是独立的。现在Roy希望将自己被抓的概率控制在P以下的同时,让自己抢劫到尽可能多的钱。

思路:因为对于每个银行的决策只有两种选项:抢与不抢,所以这是个01背包。相对于被抓的概率,逃脱的概率更好求,最后我们只需1-逃脱的概率即可。

           但是因为概率是个小数,我们没法用其表示状态:在某个概率小,能抢到的最多钱。所以,我们要将抢到的钱作为下标,从而将DP的状态定义为:在抢得i万元钱时,能逃脱的最大概率。

           最后,我们只需线性的扫一遍,找出最大的i,使dp[i]大于等于最终的逃脱概率就行。

注意:题目中给的样例有很大的迷惑性。刚开始读题把题意读错了,以为只是普通的求和。没有看到概率。

代码如下:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>

using namespace std;

const double INF = 0x3f3f3f3f;
const double EPS = 1e-6;

int v[110];
double dv,dw[110],dp[10010];

int dcmp(double x)
{
    if(fabs(x) < EPS)
        return 0;
    else if(x < 0)
        return -1;
    else
        return 1;
}

int main(void)
{
    //freopen("input.txt","r",stdin);
    int T,N;
    scanf("%d",&T);
    while(T--){
        scanf("%lf%d",&dv,&N);
        int sum = 0;
        for(int i = 0; i < N; ++i){
            scanf("%d%lf",v+i,dw+i);
            dw[i] = 1.0 - dw[i];
            sum += v[i];
        }
        memset(dp,0,sizeof(dp));
        dp[0] = 1;
        for(int i = 0; i < N; ++i)
            for(int j = sum; j >= v[i]; --j)
                dp[j] = max(dp[j],dp[j-v[i]] * dw[i]);
        for(int i = sum; i >= 0; --i){
            if(dcmp(dp[i] - 1.0 + dv) >= 0){
                printf("%d\n",i);
                break;
            }
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值