hdu2955 Robberies(01背包)

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=2955

题目大意:

有个人要去抢劫银行,在这之前他对自己抢劫的行为进行了风险估计,抢不同的银行获得的前不同风险也不同。抢银行时他有一个最高风险的上限,现在问在不超过最高风险的情况下(不被抓),他最多能抢多少钱。

思路:

题目给了两个变量,风险指数和价值,很容易想到就是01背包。

如果我们把风险当做容量,抢一个银行的钱当做价值,只要算出最大风险以内获得的最大价值。

但是风险是float型浮点数,我们放不到数组里面去。如果考虑将浮点数化为整数,float型精确值有7位有效数字,这样放大的话,数组也开不下。

最重要的是!我抢两个银行,风险不是单纯的相加!

这是我最初犯的错误= =。。。。

所以先分析一下,抢多个银行时候的风险计算:如果假设我只抢两个银行,被抓的概率分别为a,b。抢完以后,有3种情况:1、同时被两个银行抓。2、被其中一个银行抓。3、没有银行抓我。我要考虑的,只是前两个情况。所以我的风险就是1-P(3)。

P(3)就是没有银行抓我,那么我不被两个银行抓的概率分别是1-a和1-b,两者同时发生的概率就是P(3)=(1-a)*(1-b)。

所以我的风险就是1-P(3)。

-----------------------------------------------------------------------------------------------------------------------------------------------------

再重新考虑问题的求解:既然不能把风险当容量,我就尝试把抢来的钱的总和当做容量,风险当做价值。

此时我要做的就是:求出当前抢到的钱的最小被抓风险。

所以我设一个dp[ j ],代表价值为j时的最小被抓概率。这里最小的被抓概率==最大的逃脱概率,所以可以替代掉。

最后我找到那个风险小于最大上限的价值即可。

代码:

#include<stdio.h>
#include<string.h>
#include<math.h>
double max(double a,double b)
{
	if(a>b)return a;
	else return b;
}
struct node {
	
	int m;
	double p;
}a[105];
double dp[10005];
int main()
{
	int T,i,k,N,x,j;
	double P;
	scanf("%d",&T);
	while(T--)
	{
		int sum=0;
		memset(dp,0,sizeof(dp));
		scanf("%lf%d",&P,&N);
		x=1;
		for(i=1;i<=N;i++)
		{
		scanf("%d%lf",&a[i].m,&a[i].p);
		sum+=a[i].m;
		a[i].p=1-a[i].p;
		}
		dp[0]=1;     //初始化,没有抢的时候被抓风险为0.
		for(i=1;i<=N;i++)
		for(j=sum;j>=a[i].m;j--)
		{
			dp[j]=max(dp[j],dp[j-a[i].m]*a[i].p);
		}
      printf("%d\n",j);
	}
	return 0;
}
/*
5
0.45 3
1 0.255
2 0.145
3 0.051
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值