欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

HDU2955(Robberies)

程序员文章站 2022-07-07 22:54:10
...

题目传送门

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;
}

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

相关标签: 动态规划 算法