hdu2955——Robbers——————【01背包】

来源:互联网 发布:网络宠物医生在线咨询 编辑:程序博客网 时间:2024/06/03 21:51

/**

   解题思路:这道题是01背包的变型。通常的题目是dp[i]代表背包装重量为i的物品的价值。而这个题目是将价值作为背包容量,将不被捉到的概率作为背包的值。状态转移方程为dp[j]=max(dp[j],dp[j-cost]*weight)。

*/

题目大意:有人想抢劫银行,给定T,代表T组测试样例,给定一个概率P即抢劫被捉概率要控制在该概率内,给一个n即有几个抢劫目标,下边n行分别是Mi,Pi,代表n个银行的存款总值和抢劫该银行的被捉率。问在小于等于P概率的前提下,能抢到的最大金额。

/**    01背包    Zero_One_Pack(cost,weight){                for(i=V;i>=cost;i--){                     dp[i]=max(dp[i],dp[i-cost]+weight);        }    }    初始化时,如果要求恰好装满背包,dp[0]=0,dp[1-V]=-lim。    则合法状态为将价值为0,耗费为0的物品把容量为0的背    包装满,其他都为非法状态。*/#include<iostream>#include<stdio.h>#include<algorithm>using namespace std;const int MAXN=110;double lim_dan,dp[MAXN*MAXN];int each_mon[MAXN],V;double each_safe[MAXN];double max(double a, double b){    return a>b?a:b;}void Zero_One_Pack(int cost,double weight){    for(int j=V;j>=cost;j--){                                    //由于是独立事件,概率需要相乘        dp[j]=max(dp[j],dp[j-cost]*weight);    }}int main(){    int t,n;    cin>>t;    double lim_dan;    while(t--){        V=0;        memset(dp,0,sizeof(dp));    //不必完全装满,初始化为0        dp[0]=1;                    //初始化当抢劫0价值时的安全率为1        cin>>lim_dan>>n;        for(int i=0;i<n;i++){            double rate_dan;            cin>>each_mon[i]>>rate_dan;            each_safe[i]=1-rate_dan;    //计算抢劫每个银行的安全率            V+=each_mon[i];             //背包总容量        }        for(int i=0;i<n;i++){           //枚举所有银行            Zero_One_Pack(each_mon[i],each_safe[i]);        }        int i;        for( i=V;i>=0;i--){                         //抢劫价值为i的钱不被捉到的概率大于等于预定概率,该价值为临界值            if(dp[i]>=1-lim_dan){                break;            }        }        printf("%d\n",i);    }    return 0;}


0 0