01背包变形
一般人第一眼看去都是dp被捉到的概率,找抢的钱的最大值,但是dp浮点数是很不现实的,那么就要转换,转换成dp所有的和,找最大的安全概率。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct P
{
int mon;
double gai;
}p[10005];
double dp[10005];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(dp,0,sizeof(dp));
int n;
double ps;
scanf("%lf %d",&ps,&n);
ps=1-ps;
int sum=0;
for(int i=0;i<n;i++)
{
scanf("%d%lf",&p[i].mon,&p[i].gai);
p[i].gai=1-p[i].gai;//转化成安全概率
sum+=p[i].mon;
}
dp[0]=1;
for(int i=0;i<n;i++)
for(int j=sum;j>=p[i].mon;j--)
{
dp[j]=max(dp[j],dp[j-p[i].mon]*p[i].gai);//前j的钱里面,如果不抢劫p[i]的钱就不改变概率,如果抢劫,就是前j内减去p[i]的概率*抢劫p[i]的概率
//这个地方第二层循环正着循环就会WA,因为那样会默认会抢劫前面的银行
//二维正序,一维倒序
}
for(int i=sum;i>=0;i--)
{
// cout << dp[i] << endl;
if(dp[i]>ps)
{
printf("%d\n",i);//从后往前找到第一个符合安全概率的值并且输出
break;
}
}
}
return 0;
}