思路:一开始想到了要用01背包做,但是发现逃跑概率是实数。。。说明这个思路行不通(别跟我说扩大到整数。。。这题的实数精度太高行不通的)果断转换思路(上网百度),把获得的金额看成背包容积,逃脱率(注意是逃脱率,不是被抓率,概率应该是(1-被抓率),并且是相乘)看成物品,问题就转化成了,在逃脱率范围内,最大获得的金额是多少;
代码如下:
#include <iostream>
#include <algorithm>
#include <math.h>
#include <cmath>
using namespace std;
/*在p范围内求解maxsum_mj;
对比01背包,应该是在风险范围内求解,最大的收益
不计算被抓的概率,而是逃脱 的概率*/
int main()
{
int t;
cin>>t;
while(t--)
{
double dp[20000];
for(int i=1;i<20000;i++)
dp[i]=0;
dp[0]=1;//如果什么都没有偷,就是安全的
int n;
int w[10000];
int sum=0;
double v[10000];
double volume;
cin>>volume>>n;
volume=1-volume;//安全的逃脱概率
for(int i=1;i<=n;i++)
{
cin>>w[i]>>v[i];
v[i]=1-v[i];//抢了i这个银行后逃脱的概率
sum+=w[i];
}
for(int i=1;i<=n;i++)
{
for(int j=sum;j>=w[i];j--)
{
dp[j]=max(dp[j],dp[j-w[i]]*v[i]);//代表i这家抢不抢,抢了就风险就会变,dp[j]代表在i个银行中抢j块钱,最高的逃脱几率
}
}
for(int i=sum;i>=0;i--)
{
if(dp[i]>=volume)
{
cout<<i<<endl;
break;
}
}
}
return 0;
}