HDU_2955 Robberies

HDU_2955 Robberies


Problem Description
The aspiring Roy the Robber has seen a lot of American movies, and knows that the bad guys usually gets caught in the end, often because they become too greedy. He has decided to work in the lucrative business of bank robbery only for a short while, before retiring to a comfortable job at a university.


For a few months now, Roy has been assessing the security of various banks and the amount of cash they hold. He wants to make a calculated risk, and grab as much money as possible.


His mother, Ola, has decided upon a tolerable probability of getting caught. She feels that he is safe enough if the banks he robs together give a probability less than this.
 

Input
The first line of input gives T, the number of cases. For each scenario, the first line of input gives a floating point number P, the probability Roy needs to be below, and an integer N, the number of banks he has plans for. Then follow N lines, where line j gives an integer Mj and a floating point number Pj .
Bank j contains Mj millions, and the probability of getting caught from robbing it is Pj .
 

Output
For each test case, output a line with the maximum number of millions he can expect to get while the probability of getting caught is less than the limit set.

Notes and Constraints
0 < T <= 100
0.0 <= P <= 1.0
0 < N <= 100
0 < Mj <= 100
0.0 <= Pj <= 1.0
A bank goes bankrupt if it is robbed, and you may assume that all probabilities are independent as the police have very low funds.
 

Sample Input

3

0.04 3

1 0.02

2 0.03

3 0.05

0.06 3

2 0.03

2 0.03

3 0.05

0.10 3

1 0.03

2 0.02

3 0.05
 

Sample Output

2

4

6
 

本题意思就是说,抢匪抢劫银行j的金额是Mj,被抓的概率是Pj,当被抓的概率小于P时,抢匪是可以逃跑的,现在要求抢匪在可以逃脱的情况下抢夺的最大金额;

分析:通过题意我们可以很容易的想到这是一个背包问题,但是这是一个带浮点类型的背包,数组下标时浮点类,所以我们需要转化问题;我们把银行的所有金额作为背包的最大容量V,不被抓的概率作为价值;所以我们的转移方程为

dp[j] = max(dp[j - p[i]] * (1 - m[i]), dp[j]);这样我们找到容量最大时满足dp[V]>1-P便可,此时的V既是结果;

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
int m[107];
double dp[10007],P[107];
using namespace std;
int main()
{
	int T,N;
	double p;
	int i,j;
	scanf("%d",&T);
	while(T--)
	{
		int sum=0;
		scanf("%lf%d",&p,&N);
		for(i=0;i<N;i++)
		{
			scanf("%d%lf",&m[i],&P[i]);
			sum+=m[i];
		}
		dp[0]=1;
		for(i=1;i<=sum;i++)//初始化数组;
		dp[i]=0;
		for(i=0;i<N;i++)//转移方程;
		{
			for(j=sum;j>=m[i];j--)
			{
				dp[j]=max(dp[j-m[i]]*(1-P[i]),dp[j]);
			}
		}
		for(i=sum;i>=0;i--)遍历找最大的值;
		{
			if(dp[i]>(1-p))
			{
				printf("%d\n",i);
				break;
			}
		}
	}
}

以上做法是本人在一错误的做法后写的;本人在刚开始或许和和多人一样,将概率转化为整形作为背包的容量,这大概都是做题人的第一反应,不管怎么样,先试一下,本人写出代码过了样例;不过,后来的WA,开始让人不得费解,仔细想想原来是浮点类型的概率没有声明有多少位的小数,通过题目的样例,开始我们都会将概率*100转化为整型,后来接着改为*100000,想着开大些会不会有幸AK,不过都是徒劳的,浮点类的小数太多了,所以此方法行不通的;

附上本人的错误的代码;

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
int m[1007],Q[1007];
double P[1007];
int dp[10000007];
int main()
{
	int T,n,q,i,j;
	double p;
	scanf("%d",&T);
	while(T--)
	{
		memset(dp,0,sizeof(dp));
		scanf("%lf%d",&p,&n);
		q=(int)(p*1000000);
		//printf("%d\n",q);
		for(i=0;i<n;i++)
		{
			scanf("%d%lf",&m[i],&P[i]);
			Q[i]=(int)(P[i]*1000000);
		}
		for(i=0;i<n;i++)
		{
			for(j=q;j>=Q[i];j--)
			{
				dp[j]=max(dp[j-Q[i]]+m[i],dp[j]);
			}
		}
		printf("%d\n",dp[q]);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_42140101/article/details/83474200
今日推荐