hdu-2955 Robberies---01背包变形

题目链接:

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

题目大意:

有一个强盗要去几个银行偷盗,他既想多投点钱,又想尽量不被抓到。已知各个银行

的金钱数和被抓的概率,以及强盗能容忍的最大被抓概率。求他最多能偷到多少钱?

思路:

这里的最大被抓概率,正面求解是不好求的,而且是浮点数,不能当做背包的维数,所以只能做背包的价值,正面求解最小被抓概率是不好求的,有很多情况,所以应该反面来求解,求解最大的不被抓的概率,这样的话就是直接连乘了,p = (1-p1)*(1-p2)*(1-p3)(其中p为最大不被抓概率,p1,p2,p3分别是在银行123被抓的概率)

所以这里应该把能抢到的钱作为背包,概率作为价值,每次求解当前抢到的钱的最大不被抓概率。

dp[j] = max(dp[j],dp[j-Bag[i].v]*(1-Bag[i].p))(dp[j]表示在抢到的钱为j的时候最大的不被抓的概率);

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 105;
 4 const int maxm = 1e4+10;
 5 const int INF = 1e9+7;
 6 int v[maxn];
 7 double w[maxn];
 8 double dp[maxm];
 9 int T, n;
10 double m;
11 int main()
12 {
13     cin >> T;
14     while(T--)
15     {
16         cin >> m >> n;//m为能容忍的最大被抓概率
17         int sum = 0;
18         for(int i = 0; i < n; i++)cin >> v[i] >> w[i], sum += v[i];
19         //dp[i][j]表示偷前i家银行,价值为j的最大不被抓的概率
20         memset(dp, 0, sizeof(dp));
21         dp[0] = 1;
22         for(int i = 0; i < n; i++)
23         {
24             for(int j = sum; j >= v[i]; j--)
25                 dp[j] = max(dp[j], dp[j - v[i]]*(1- w[i]));
26         }
27         for(int j = sum; j >= 0; j--)
28         {
29             //cout<<j<<" "<<dp[j]<<endl;
30             if(dp[j] > 1 - m)
31             {
32                 cout<<j<<endl;
33                 break;
34             }
35         }
36     }
37     return 0;
38 }
原文地址:https://www.cnblogs.com/fzl194/p/8783595.html