01背包 + 概率 之 hdu 2955

来源:互联网 发布:软件模拟计算热量传递 编辑:程序博客网 时间:2024/05/31 19:08
//  [7/20/2014 Sjm]/*看到此题时,第一个想法是:以P作为体积,Pj作为费用,Mj作为价值。但是,double类型的不能作为数组下标,于是此法行不通。 于是,从另一角度考虑:被抓的概率不能超过上限,即不被抓的概率要大于下限(下限 = 1 - 被抓概率的上限)。以总的银行金额作为体积,每一个银行金额作为费用,不被抓的概率作为价值。即 dp[i][j] := 抢劫了前 i 个银行,所获金额至多为 j 的最大不被抓的概率。另外只有当每一个银行都没抓到 Roy 才可以。所以求概率时,要相乘。由此可求出答案。********注意********初始化时,dp[0] = 1,若不抢劫银行,则不被抓的概率为 1。*/
#include <iostream>#include <cstdlib>#include <cstdio>#include <algorithm>using namespace std;const int MAX = 105;const int MAX_mil = 10005;struct node {    int millions;    double prb;};node arr[MAX];int sum;double P;int N;double dp[MAX_mil];int Solve(){    fill(dp, dp + sum + 1, 0);    dp[0] = 1;    for (int i = 1; i <= N; ++i) {        for (int j = sum; j >= arr[i].millions; --j) {            dp[j] = max(dp[j], dp[j - arr[i].millions] * arr[i].prb);        }    }    for (int j = sum; j >= 0; --j) {        if (dp[j] > P) {            return j;        }    }    return 0;}int main(){    //freopen("input.txt", "r", stdin);    int T;    scanf("%d", &T);    while (T--) {        sum = 0;        scanf("%lf %d", &P, &N);        P = 1 - P;        for (int i = 1; i <= N; ++i) {            scanf("%d %lf", &arr[i].millions, &arr[i].prb);            arr[i].prb = 1 - arr[i].prb;            sum += arr[i].millions;        }        printf("%d\n", Solve());    }    return 0;}
0 0
原创粉丝点击