题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2955
题目给了每个银行的钱和被抓的概率,由于要抢尽量多的钱,所以要保证尽量不被抓,而抢多个银行之后不被抓的概率是抢每一个银行不被抓的概率之 积,dp[]表示抢到下标所对应的钱时,此时不被抓的概率,题目给出了最终不能高于被抓概率 P,不被抓的概率就不能低于(1-P),所以最后只需要逆序遍历dp,找到第一个大于等于1-P的dp[i],就能够保证i最大,即抢到的钱最多。
dp[j]=max(dp[j], dp[j-v[i]]*p[i]);
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <cstdlib> using namespace std; #define N 110 #define met(a, b) memset(a, b, sizeof(a)) double dp[N*N], p[N], P; ///dp[i]表示抢到价值为i,此时不被抓的概率, int n, v[N]; int main() { int T; scanf("%d", &T); while(T--) { met(v, 0); met(p, 0); met(dp, 0); scanf("%lf %d", &P, &n); int sum = 0; for(int i=1; i<=n; i++) { scanf("%d %lf", &v[i], &p[i]); p[i]=1-p[i];///p[i]表示抢第i个银行,不被抓的概率; sum+=v[i]; } dp[0]=1;///没抢的时候肯定没被抓,概率为1; for(int i=1; i<=n; i++) { for(int j=sum; j>=v[i]; j--) { dp[j]=max(dp[j], dp[j-v[i]]*p[i]); } } for(int i=sum; i>=0; i--) { if(dp[i]>1-P) { printf("%d ", i); break; } } } return 0; }