1. 程式人生 > >hdu2955_01揹包+概率計算

hdu2955_01揹包+概率計算

動態規劃訓練1——hdu2955

                 Robberies
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 32557 Accepted Submission(s): 11815

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.

 本題為簡單的01揹包問題,解題步驟及動態規劃的狀態劃分容易得到。但是此題有幾個明顯的易錯點:
   1.此題是概率型問題,計算概率時不能簡單相加,而是滿足概率運算的基本規則。在本題中,要求被抓的概率嚴格小於一期望概率。若直接從此角度入手,概率的計算比較困難。因此可考慮計算(1-被抓的概率)>(1-期望)。
   2.由於此題中的概率為浮點數,所以不能用做揹包容量,應考慮將所能獲得的最大價值作為最大容量。最後查詢滿足要求的最大價值。

 程式碼如下:

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <string.h>
#include <string>
#include <algorithm>
#include <stdlib.h>
#include <math.h>
using namespace std;
double dp[10005], P[105],pro;
int M[105], N;
int main(void) {
	int T; scanf("%d", &T);
	while (T--) {
		scanf("%lf%d", &pro, &N);
		int sum = 0;
		for (int i = 0; i < N; ++i)
			scanf("%d%lf", &M[i], &P[i]), sum += M[i];
		memset(dp, 0, sizeof(dp)); dp[0] = 1;
		for (int i = N - 1; i >= 0; --i)
			for (int j = sum; j >= M[i]; j--)
				dp[j] = max(dp[j], dp[j - M[i]] * (1 - P[i]));
		for (int i = sum; i >= 0; --i)
			if (dp[i] > 1 - pro) {
				printf("%d\n", i);
				break;
			}
	}
	return 0;
}