http://lightoj.com/volume_showproblem.php?problem=1079
Just another Robbery
As Harry Potter series is over, Harry has no job. Since he wants to make quick money, (he wants everything quick!) so he decided to rob banks. He wants to make a calculated risk, and grab as much money as possible. But his friends - Hermione and Ron have decided upon a tolerable probability P of getting caught. They feel that he is safe enough if the banks he robs together give a probability less than P.
Input
Input starts with an integer T (≤ 100), denoting the number of test cases.
Each case contains a real number P, the probability Harry needs to be below, and an integer N (0 < N ≤ 100), the number of banks he has plans for. Then follow N lines, where line j gives an integer Mj (0 < Mj ≤ 100) and a real number Pj . Bank j contains Mj millions, and the probability of getting caught from robbing it is Pj. A bank goes bankrupt if it is robbed, and you may assume that all probabilities are independent as the police have very low funds.
Output
For each case, print the case number and the maximum number of millions he can expect to get while the probability of getting caught is less than P.
Sample Input |
Output for 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 |
Case 1: 2 Case 2: 4 Case 3: 6 |
Note
For the first case, if he wants to rob bank 1 and 2, then the probability of getting caught is 0.02 + (1 - 0.02) * .03 = 0.0494 which is greater than the given probability (0.04). That‘s why he has only option, just to rob rank 2.
第一次接触概率的01背包, 感觉挺神奇的, 虽然在比赛的时候没写出来, 补题也是在好几天后, 但能看懂, 还是很高兴, 提示自己以后要看点背包和 dp 的题了, 虽然比赛很烂, 但是我觉得这样挺好的,可以时常弥补自己的不足
#include<stdio.h> #define N 110 #define min(a,b) (a)>(b)?(b):(a) int v[N]; double dp[N][N*N], p[N]; /*** 题意:给出银行的个数和被抓概率上限。在给出每个银行的钱和抢劫这个银行被抓的概率。 求不超过被抓概率上线能抢劫到最多的钱。 dp题,转移方程 dp[i][j] = min(dp[i-1][j] , dp[i-1][j-v[i]]) , dp[i][j]表示前 i 个银行抢劫到 j 这么多钱被抓的概率。 初始化时 dp[0][0] = 0 , 因为 dp[0][1~n]是不可能的情况,dp[0][1~n]=-1 ***/ int main() { int T, iCase=1; scanf("%d", &T); while(T--) { int i, j, n, sum=0; double P; scanf("%lf%d", &P, &n); for(i=1; i<=n; i++) { scanf("%d%lf", &v[i], &p[i]); sum += v[i]; } for(i=1; i<=sum; i++) dp[0][i] = -1; dp[0][0] = 0; for(i=1; i<=n; i++) for(j=0; j<=sum; j++) { if(j<v[i] || dp[i-1][j-v[i]]<-0.5) dp[i][j] = dp[i-1][j]; else if(dp[i-1][j]<0) dp[i][j] = dp[i-1][j-v[i]] + (1-dp[i-1][j-v[i]])*p[i]; else dp[i][j] = min(dp[i-1][j], dp[i-1][j-v[i]]+(1-dp[i-1][j-v[i]])*p[i]); } int ans = 0; for(i=0; i<=sum; i++) if(dp[n][i]>-0.5 && dp[n][i]<P) ans = i; printf("Case %d: %d\n", iCase++, ans); } return 0; }