一般的解法
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
double f[110][10005];
int main()
{
int t;
scanf("%d",&t);
double pp,p[150];
int n,s[150];
while(t--)
{
scanf("%lf%d",&pp,&n);
pp=1-pp;
int sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d%lf",&s[i],&p[i]);
p[i]=1-p[i];
sum+=s[i];
}
memset(f,0,sizeof(f));
f[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=sum;j>=0;j--)
{
f[i][j]=f[i-1][j];
if(f[i-1][j-s[i]]*p[i]>=pp)
f[i][j]=max(f[i-1][j],f[i-1][j-s[i]]*p[i]);
}
int ans=0;
for(int i=1;i<=n;i++)
for(int j=0;j<=sum;j++)
if(f[i][j]>0)
{
//cout<<f[i][j]<<'*'<<endl;
ans=max(ans,j);
}
cout<<ans<<endl;
}
return 0;
}
就地滚动的解法
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
double f[10005];
int main()
{
int t;
scanf("%d",&t);
double pp,p[150];
int n,s[150];
while(t--)
{
scanf("%lf%d",&pp,&n);
pp=1-pp;
int sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d%lf",&s[i],&p[i]);
p[i]=1-p[i];
sum+=s[i];
}
memset(f,0,sizeof(f));
f[0]=1;
for(int i=1;i<=n;i++)
for(int j=sum;j>=0;j--)
{
//f[i][j]=f[i-1][j]; //不抢的概率
if(f[j-s[i]]*p[i]>=pp)
f[j]=max(f[j],f[j-s[i]]*p[i]); //抢的概率
}
int ans=0;
for(int i=1;i<=n;i++)
for(int j=0;j<=sum;j++)
if(f[j]>0)
{
ans=max(ans,j);
}
cout<<ans<<endl;
}
return 0;
}
//f[i][j]表示抢了前i个银行获得利益j的最大的不被抓的概率