Robberies HDU - 2955(01背包)

本文探讨了一个特殊场景下的01背包问题——如何在被抓概率小于给定值的前提下,从多个银行中选择抢劫以获取最大金额。通过巧妙转换,将被抓概率转化为逃跑概率,并将其视为背包问题中的价值,而将银行的钱数视为体积,从而求解最大钱数。文章详细介绍了算法实现过程,包括使用DP数组存储逃跑概率,以及最终确定最大可抢劫金额。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:
某人要抢劫银行,给出你一个最大被抓的概率p,和银行个数,随后给出每个银行的钱数和被抓的概率,要求在被抓概率小于p的情况下获得的最大的money。

题解:
妥妥的一道01背包,本来把被抓概率当成01背包中的体积了,只需要把所有概率都×100在处理就好了,后来发现不行,首先对于多个银行都去抢的话概率是相乘的,然后他给的概率不见得就是两位小数的,所以此路不通。
仔细想想01背包的内容,遍历一遍物品(再此题中为银行)是不能少的,然后需要一个取值为正整数的变量,好像只有钱数是正整数了,于是我们想着向这个方向转化。被抓概率小于p是必须的,那么我们可以转化为逃跑概率要大于1 - p,我们可以将钱数作为01背包中的体积V,把逃跑概率作为价值val,只需要找出逃跑概率 > p 的最大钱数就是答案

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

using namespace std;

int t, n;
double dp[12000];
int money[130];
double ex[130], p;

int main()
{
	scanf("%d", &t);
	while(t--)
	{
		scanf("%lf%d", &p, &n);
		int sum = 0;
		for(int i = 1; i <= n; ++ i)
		{
			scanf("%d%lf", &money[i], &ex[i]);
			sum += money[i];
		}
		memset(dp, 0, sizeof(dp));
		dp[0] = 1;
		for(int i = 1; i <= n; ++ i)
		{
			for(int j = sum; j >= money[i]; --j)
			{
					dp[j] = max(dp[j], dp[j - money[i]] * (1 - ex[i]));
			}
		}
		for(int i = sum; i >= 0; -- i)
		{
			if(1.0 - dp[i] < p)
			{
				cout << i << endl;
				break;
			}
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值