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 }
越努力,越幸运