HDU 2955 Robberies

传送门

01背包,,,非常灵活的变形。
给你很多个银行(物品),每个银行的钱数(重量)和被抓概率(价值),一个人去抢劫这些银行,但是总体被抓概率要小于一个固定值P,在这基础上最多能抢多少钱。(一个银行要么不被抢,要么全被抢)

乍一看肯定是钱数当成价值啊,因为正好要求最大化钱数,所以被抓概率就是重量了?。。不行的。概率值是个小数,而dp[]的下标就是当前背包容量,这概率连乘起来位数多了去了,数组下标没法搞。

所以只能概率当成价值,钱数当成重量(N*Mj<=10000)。然后再看这题,它给的是被抓概率,然而总体被抓概率不是被抓概率的连乘,所以我们翻一下,把每个银行的不被抓概率当成价值。
这就变成了:(在可供抢劫范围为前i个银行的情况下,)抢劫不超过当前钱数下,最大的不被抓概率是多少。

但是,细心的话你会发现一个问题。 不抢一家银行的不被抓概率最大,那么所有钱数下的最大不被抓概率都是1。怎么办?其实考虑dp的初始值也能发现,按理说,本来dp的初值应该都是1.0,但那样的话就永远不会再被更新了。

所以要加个限制,必须恰好装满。 所以只有dp[0]的初值是1.0,其他都是不合法的值(因为是乘积传递,用0.0就可以了)。
现在问题变成了:(在可供抢劫范围为前i个银行的情况下,)恰好抢劫当前钱数下,最大的不被抓概率是多少。

接下来运行dp,最后,我们从大到小枚举钱数,当概率第一次大于P时,此时的钱数就是答案了。为什么能这么求?因为我们算的都是最大不被抓概率,如果最大概率都无法大于一个下限,那么意味着这个钱数下肯定无解;如果之后钱数下的概率比答案更大,那么也没有用,因为只要概率大于下限了,我们并不关心哪个更大,我们只关注哪个抢的钱多。


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <string>
#include <queue>
using namespace std;

int N, T;
double P;
double dp[10001];            // 恰好!!抢劫这些钱的最大逃脱概率,背包容量是当前抢劫钱数
double p[101];
int w[101];
int sum;                     // 背包容量

void init()
{
	fill(dp + 1, dp + 10001, 0.0);        // 恰好装满系列。价值是乘积,需要额外注意初始化!
	dp[0] = 1.0;
	sum = 0;
}

int main()
{
	
	scanf("%d", &T);
	for (; T--;)
	{
		scanf("%lf%d", &P, &N);
		P = 1.0 - P;
		init();
		for (int i = 1; i <= N; i++)
		{
			scanf("%d%lf", &w[i], &p[i]);
			p[i] = 1.0 - p[i];                // 所谓逃脱概率 = (1-p[1])*(1-p[2])*(1-p[3])...   p[i]表示该次被抓概率
			sum += w[i];
		}

		for (int i = 1; i <= N; i++)
		{
			for (int j = sum; j >= w[i]; j--)
			{
				dp[j] = max(dp[j], dp[j - w[i]] * p[i]);
				//cout << "   i= " << i << " j= " << j << "   " << dp[j] << endl;   弄不清的时候,不妨看看运行过程
			}
		}
		for (int i = sum; i >= 0; i--)
		{
			if (dp[i] > P)
			{
				printf("%d\n", i);
				break;
			}
		}
	}

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值