HDU2955Robberies(DP)
http://acm.hdu.edu.cn/showproblem.php?pid=2955
题目是说一小偷偷东西,第i个物品的价值是M[i],被抓的概率是p[i],现在要使得在被抓的概率在P以下时的所能偷得的最大价值。
不同于以往的01背包,这里需要将价值作为物品的大小。同时如果偷A被抓的概率是Pa,偷B被抓的概率是Pb那么偷两个物品被抓的概率就是
1-(1-Pa)*(1-Pb)
这时令DP[i][j]代表对于前i个物品偷得的价值为j时的最小的被抓的概率,这时可以得到状态转移方程:
DP[i][j] = MIN( DP[i-1][j], 1-(1-DP[i-1][j-M[i]])*(1-p[i]) )
最后的结果就是对于所有的DP[N][i]<P的最大的j
同样可以将状态压缩到一维的空间,注意边界(最初时):
DP[i] = 1;一旦偷东西就会被抓
DP[0] = 0;什么都没偷一定不会被抓
1 #include <map> 2 #include <set> 3 #include <stack> 4 #include <queue> 5 #include <cmath> 6 #include <ctime> 7 #include <vector> 8 #include <cstdio> 9 #include <cctype> 10 #include <cstring> 11 #include <cstdlib> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 #define INF 0x3f3f3f3f 16 #define inf (-((LL)1<<40)) 17 #define lson k<<1, L, mid 18 #define rson k<<1|1, mid+1, R 19 #define mem0(a) memset(a,0,sizeof(a)) 20 #define mem1(a) memset(a,-1,sizeof(a)) 21 #define mem(a, b) memset(a, b, sizeof(a)) 22 #define FOPENIN(IN) freopen(IN, "r", stdin) 23 #define FOPENOUT(OUT) freopen(OUT, "w", stdout) 24 25 template<class T> T CMP_MIN(T a, T b) { return a < b; } 26 template<class T> T CMP_MAX(T a, T b) { return a > b; } 27 template<class T> T MAX(T a, T b) { return a > b ? a : b; } 28 template<class T> T MIN(T a, T b) { return a < b ? a : b; } 29 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; } 30 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b; } 31 32 //typedef __int64 LL; 33 //typedef long long LL; 34 const int MAXN = 4000000+10; 35 const int MAXM = 2000010; 36 const double eps = 1e-1; 37 38 double DP[11000], w[110], P; 39 int c[110], N; 40 41 int main() 42 { 43 int T; 44 while(~scanf("%d%*c", &T)) while(T--) 45 { 46 mem1(DP); 47 scanf("%lf%d", &P, &N); 48 int S = 0; 49 for(int i=0;i<N;i++) 50 { 51 scanf("%d %lf", &c[i], &w[i]); 52 S += c[i]; 53 } 54 for(int i=S;i>=0;i--) DP[i] = 1; 55 DP[0] = 0; 56 for(int i=0;i<N;i++) 57 { 58 for(int j=S;j>=c[i];j--) 59 { 60 DP[j] = MIN(DP[j], 1.0-(1-DP[j-c[i]])*(1-w[i])); 61 } 62 } 63 int ans = 0; 64 for(int i=0;i<=S;i++) if(DP[i] <= P) ans = i; 65 printf("%d\n", ans); 66 } 67 return 0; 68 }