#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;//#include<algorithm> using namespace std;这两句是因为下面要调用库函数中的max函数
double dp[10005];//储存的是不被抓到的概率,最多一百家银行,每家最多抢100,所以取10005
struct node//建议背包问题使用一个结构体储存他的价值和代价
{
int Mj;
double Pj;//建议浮点数都用double,注意格式%lf
};
int main()
{
int T;
node bank[105];
scanf("%d",&T);//变量名最好和题目中所给的统一
while(T--)
{
double P;
scanf("%lf",&P);
int N;
scanf("%d",&N);
int i,j,k;
int Sum=0;
dp[0]=1.0;
for(i=1;i<=N;i++)
{
scanf("%d%lf",&bank[i].Mj,&bank[i].Pj);
bank[i].Pj=1.0-bank[i].Pj;//题目给的是被抓到的概率,应该转换成不被抓到的概率,因为多次不被抓到的概率相乘才是总的不被抓到的概率
Sum+=bank[i].Mj;//因为此题背包容量不知道,所以不能采取边输入边计算的模式,需要先全部输入,求出背包容量总和
}
memset(dp,0,sizeof(dp));//动态规划前要注意两点1.清空dp数组2.处理边界条件和dp[0];
dp[0]=1.0;//抢0元的不被抓到概率一定为1.0
for(i=1;i<=N;i++)//i从几开始要根据下方来,有的动态规划方程中有dp[i-2],则需要从i=2开始。
{
for(j=Sum;j>=bank[i].Mj;j--)//把判断条件j>=bank[i].Mj放在for循环中
{
dp[j]=max(dp[j],dp[j-bank[i].Mj]*bank[i].Pj);//成立条件条件是dp[j-bank[i].Mj],之前抢过钱,动态规划转移方程是:dp[j]=max(dp[j],dp[j-bank[i].Mj]*bank[i].Pj) 其中,dp[j]表示抢j块大洋的最大的逃脱概率,
}
}
for(i=Sum;i>=0;i--)//从最大值往下递减,求if成立时最大的i
if(dp[i]>1.0-P)//P给的是被抓到的概率,dp求的是不被抓到的概率,所以要1.0-P,
{
printf("%d\n",i);
break;
}
}
return 0;
}
HDU2955 01背包
最新推荐文章于 2018-12-04 22:54:57 发布