hdu2955 Robberies(01背包)

只有我一个人觉得这题题意很难懂么。。。


先是给出几组数据,每组数据第一行是总被抓概率p(最后求得的总概率必须小于他,否则被抓),然后是想抢的银行数n。然后n行,每行分别是该银行能抢的钱数m[i]和被抓的概率p[i],求最大逃跑概率。被抓的概率越大,逃跑概率越小。


第一点就是最容易犯错的一点,把所求总被抓概率看成背包容量。这就有两个很明显错误,求的就是1-被抓概率=逃跑概率,限制条件和最大背包容量不能同为一属性。再者,概率为多为浮点数,精确度不高无法遍历。所以背包容量必然是钱数,因为他能抢的银行有限,钱数也是有限的。然后是求最大逃跑概率,而题中每项给出的是被抓概率,所以要先被1减一下。还有最后求得的逃跑概率随着抢银行的数量增加而减少,多抢一个银行,其钱数必将转化为概率的乘积,所以动态方程也要做出改变。最后遍历,剩余的钱数越多,说明所抢的钱数越少,逃跑几率越大。所以从大到小遍历背包容量,一旦大于p,即为最大概率跳出。


这应该是写的比较场的体会了,主要是这题多想想还是蛮有意思的~

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <string.h>
using namespace std;

const int N = 50005;

int main()
{
  //  freopen("in.txt", "r", stdin);
    int t, m0, m[N];
    double p0, p[N], ans[N];
    scanf("%d", &t);
    while(t --)
    {
        scanf("%lf%d", &p0, &m0);
        int sum = 0;
        for(int i = 0; i < m0; i ++)
        {
            scanf("%d%lf", &m[i], &p[i]);
            sum += m[i];
        }
        memset(ans, 0, sizeof(ans));
        ans[0] = 1;
        for(int i = 0; i < m0; i ++)
        {
            for(int j = sum; j >= m[i]; j --)
            {
                ans[j] = max(ans[j], ans[j - m[i]] *(1 - p[i]));
            }
        }
        for(int i = sum; i >= 0; i --)
        {
            if(ans[i] > (1 - p0))
            {
                printf("%d\n", i);
                break;
            }
        }
    }
    return 0;
}


  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值