HDU2955(Robberies)

题目传送门

在这里插入图片描述

题意

大概意思就是有一个人要去抢银行,然后算好了每个银行有多少钱,抢这个银行的风险是多少。给定银行数目和风险数,问不超过这个风险数下能抢到的最大金额。看起来好像挺简单的不就是01背包嘛,其实也道题也不简单,坑也不少。

思路

错误的思路:最开始我做这道题强行把风险数转为整数当做背包容量,然后再去做01背包,几发WA之后我不得不怀疑自己的思路的正确性。然后我开始怀疑这个浮点数是不是给的位数很多。还有就是这道题的样例给的神他妈恶心。我最开始以为风险数是叠加做加法的,还神TM合上了答案。注意:概率是做乘法,给的样例做加法竟然很巧妙的对上了,T v T~~~

正确思路:由于金额数不是很大,我们可以枚举每一个金额下的不被抓的概率最大,最后倒叙遍历金额,找到不超过给定的风险数,就是最大能抢到的金额。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
struct info{
	double p;
	int m;
}s[105];
double dp[10005];
void solve(int n,int m,double p)
{
	memset(dp,0,sizeof(dp));
	dp[0] = 1.0;
	for(int i = 1;i <= n;i++){
		for(int j = m;j >= s[i].m;j--){			//不被抓的概率 
			dp[j] = max(dp[j],dp[j-s[i].m]*(1.0-s[i].p));
		}
	}
	for(int i = m;i >= 0;i--){					//倒叙遍历,从金额最大倒叙遍历
		if((1.0-dp[i]) <= p){					//被抓的概率不超过给定的风险数
			printf("%d\n",i);
			break;
		}
	}
}
int main()
{
	int t;
	cin>>t;
	while(t--){
		double p,n;
		int sum = 0;
		cin >> p >> n;
		for(int i = 1;i <= n;i++){
			cin >> s[i].m >> s[i].p;
			sum += s[i].m;					//所有银行的钱数当做背包容量
		}
		solve(n,sum,p);
	}
	return 0;
}

愿你走出半生,归来仍是少年~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值