HDU - 2955 Robberies dynamic programming [01] backpack

Copyright: original article, please do not reprint without permission https://blog.csdn.net/DanBo_C/article/details/89889660

Robberies

Translation:

Problem Description
aspiring Roy the Robber has seen a lot of American movies, and know that the bad guys usually end up being caught, usually because they become too greedy. After retiring to the comfort of the university work before he decided only a short time in the lucrative business of the bank robbery.

For months, Roy has been evaluating the safety of banks and the amount of cash they hold. He wants to calculate risk, and as much as possible to make money.

His mother Ola has decided the possibility of being caught. If the probability of his bank robbery given below this value, she felt safe enough.

Input
The first input line is given T, which exposes the number of cases. For each scenario, the first line of input gives the floating-point P, the probability is lower than Roy needs, as well as the integer N, the number of banks that is his plan. Then follow N rows, row j where Mj is given integer and floating point Pj.
Bank j contain Mj million, and the possibility of being robbed is Pj.

Yield
for each test case, an output line, wherein the maximum number that can be obtained per million, less than the probability of being captured by the set limits.

Comments and constraints
0 <T <= 100
0.0 <= P <= 1.0
0 <N <= 100
0 <Mj <= 100
0.0 <= Pj <= 1.0
if the bank was robbed bank failures, you might think all because the police funds few probability is independent.

Input Sample
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
0.03
2 0.02
3 0.05

Sample Output
2
. 4
. 6

Problem-solving ideas:

A typical dynamic programming knapsack problem

  1. Start with the questions in the test point to the part of the interception analysis

    1
    0.04 3
    1 0.02
    2 0.03
    3 0.05

  2. Analysis:
    N (Case) = 1
    P (not caught) = 0.04
    n-(bank). 3 =
    n-(the amount of the bank robbery 0) = 1
    P (first caught Bank 0) = 0.02
    n-(1 bank robbery amount) = 2
    P (first caught a bank) = 0.03
    n-(the amount of the second bank robbery). 3 =
    P (caught second bank) = 0.05

  3. Method One: violence Search (high time complexity)

  4. Method two: search memory (than Example portion, there may time out)

  5. Method three: dynamic programming, (low time complexity) knapsack problem

  6. Because of the need as much robbery, then dp array on the opposite of calculation. For examples, it can be possible robbery 1,2,3 (3 / (1 + 2)), 4 (1 + 3), 5 (2 + 3), 6 (1 + 2 + 3). Then on the first count array dp dp [6], dp [5] ... dp (as a result of the positive sequence) [1]

  7. There are two cases, assuming that dp [3] (robbery amounting to 3)

    • If you do not choose bank 3, then dp1 [3] = dp [3]
    • If the selected bank 3, then dp2 [3] = (1-0.05) * dp [6-3]
    • Summary: dp [3] = max (dp1 [3], dp2 [3])
  8. Get transfer equation:

    dp[j] = max((1-a[i].p)*dp[j-a[i].money],dp[j]);

  9. P (caught) = 1-0.04 = 0.96

  10. And so reverse circulation dp, first appeared> = 0.96 is the optimal solution

simulation

Bank=1

dp[6] = max( (1 - 0.02) * dp[ 6-1 ] , dp[6] ) = 0
dp[5] = max( (1 - 0.02) * dp[ 5-1 ] , dp[5] ) = 0
dp[4] = max( (1 - 0.02) * dp[ 4-1 ] , dp[4] ) = 0
dp[3] = max( (1 - 0.02) * dp[ 3-1 ] , dp[3] ) = 0
dp[2] = max( (1 - 0.02) * dp[ 2-1 ] , dp[2] ) = 0
dp[1] = max( (1 - 0.02) * dp[ 1-1 ] , dp[1] ) = max( 0.98 * 1 , 0 ) = 0.98

Bank=2

dp[6] = max( (1 - 0.03) * dp[ 6-2 ] , dp[6] ) = 0
dp[5] = max( (1 - 0.03) * dp[ 5-2 ] , dp[5] ) = 0
dp[4] = max( (1 - 0.03) * dp[ 4-2 ] , dp[4] ) = 0
dp[3] = max( (1 - 0.03) * dp[ 3-2 ] , dp[3] ) = max( 0.97 * 0.98 , 0 ) = 0.9506
dp[2] = max( (1 - 0.03) * dp[ 2-2 ] , dp[2] ) = max( 0.97 * 1 , 0 ) = 0.97

Bank=3

dp[6] = max( (1 - 0.05) * dp[ 6-3 ] , dp[6] ) = max( 0.95 * 0.9506 , 0 ) = 0.90307
dp[5] = max( (1 - 0.05) * dp[ 5-3 ] , dp[5] ) = max( 0.95 * 0.97 , 0 ) = 0.9215
dp[4] = max( (1 - 0.05) * dp[ 4-3 ] , dp[4] ) = max( 0.95 * 0.98 , 0 ) = 0.931
dp[3] = max( (1 - 0.05) * dp[ 3-3 ] , dp[3] ) = max( 0.95 * 1 , 0.9506 ) = 0.9506

DP [] = {. 1, 0.97, 0.9506, 0.931, 0.9215, 0.90307}
. 1 - 0.04 = 0.96
0.97> 0.96> 0.931
. The first number is higher than 0.96 is 0.97 corresponds to the total amount of 200 robbery
i.e., the answer is 2

The complete code

#include<iostream>
#include<string>
#include<cstring>
using namespace std;
#define max(a,b) (a>b?a:b)

struct node
{
	int money;
	double p;
}Node;

double dp[10005];
int main()
{
	int N;
	cin>>N;
	while(N--)
	{
		double pBu;
		int nBank;
		cin>>pBu>>nBank;
		node a[100];
		int total=0;
		for(int i=0;i<nBank;i++)
		{
			cin>>a[i].money>>a[i].p;
			total +=a[i].money; 
		}
		memset(dp,0,sizeof(dp));
		dp[0]=1;
		for(int i=0;i<nBank;i++)
		{
			for(int j=total;j>=a[i].money;j--)
			{
				dp[j] = max((1-a[i].p)*dp[j-a[i].money],dp[j]);
			}
		}
		for(int i=total;i>=0;i--)
		{
			if(dp[i] >= 1-pBu)
			{
				cout<<i<<endl;
				break;
			}
		}

	}
}

Guess you like

Origin blog.csdn.net/DanBo_C/article/details/89889660