zoukankan      html  css  js  c++  java
  • HDU 2955 Robberies(概率DP,01背包)题解

    题意:给出规定的最高被抓概率m,银行数量n,然后给出每个银行被抓概率和钱,问你不超过m最多能拿多少钱

    思路:一道好像能直接01背包的题,但是有些不同。按照以往的逻辑,dp[i]都是代表i代价能拿的最高价值,但是这里的代价是小数,显然不能这么做。还有,被抓概率显然不能直接相加,也不能相乘(越乘越小),这里就需要一些转化。我们把被抓概率转化为逃跑概率也就是1-被抓,那么逃跑概率就能直接相乘了。dp[i]代表拿到i价值的最大逃跑概率,这样又变成了01背包。最后求逃跑概率大于等于1-m的最大的钱。

    代码:

    #include<cstdio>
    #include<set>
    #include<map>
    #include<cmath>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<cstring>
    #include<string>
    #include<sstream>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int maxn = 10000+10;
    const int INF = 0x3f3f3f3f;
    double dp[maxn];    //逃跑概率
    int val[105];
    double pr[105];
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){
            double need;
            int n,sum = 0;
            scanf("%lf%d",&need,&n);
            need = 1 - need;
            for(int i = 1;i <= n;i++){
                scanf("%d%lf",&val[i],&pr[i]);
                sum += val[i];
                pr[i] = 1 - pr[i];
            }
            memset(dp,0,sizeof(dp));
            dp[0] = 1;
            for(int i = 1;i <= n;i++){
                for(int j = sum;j >= val[i];j--){
                    dp[j] = max(dp[j],dp[j - val[i]]*pr[i]);
                }
            }
            int ans = 0;
            for(int i = sum;i >= 0;i--){
                if(dp[i] >= need){
                    ans = i;
                    break;
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    【HDOJ】1224 Free DIY Tour
    【HDOJ】1494 跑跑卡丁车
    【HDOJ】1495 非常可乐
    ACMer
    find the nth digit
    A C
    已知六条边的边长,求四面体体积
    快速排序
    {A} + {B}
    素数回文
  • 原文地址:https://www.cnblogs.com/KirinSB/p/9491693.html
Copyright © 2011-2022 走看看