http://lightoj.com/volume_showproblem.php?problem=1079
这道题搞了挺久的。。。菜哭,本来想直接贪心用性价比最高的,结果过不了样例。。。
重新看了下,发现mi<100,那么最大获得钱数就是1e4,好像可以用个背包,下标是钱数,f[i][j]表示前i个银行获得j个钱所能得到的最小被抓可能性,还要搞个bool数组表示这个钱数是否可获得。最后就找到<P的最大钱数就行了。
T=100,所以总复杂度应该是1e8,感觉海星
其实好像可以优化成一维的。。但是我懒得思考了。。。
#include<bits/stdc++.h>
#define maxl 110
#define eps 1e-8
using namespace std;
int n,ans,cas,mx;
double P;
struct bank
{
int val;double p;
}a[maxl];
double f[maxl][maxl*maxl],tmp[maxl][maxl*maxl];
bool in[maxl][maxl*maxl];
inline void prework()
{
scanf("%lf%d",&P,&n);
mx=0;
for(int i=1;i<=n;i++)
scanf("%d%lf",&a[i].val,&a[i].p),mx+=a[i].val;
}
inline void mainwork()
{
for(int i=0;i<=n;i++)
for(int j=0;j<=mx;j++)
in[i][j]=false,f[i][j]=0,tmp[i][j]=0;
in[0][0]=true;tmp[0][0]=1;double nxt;
for(int i=1;i<=n;i++)
for(int j=mx;j>=0;j--)
{
if(in[i-1][j])
{
in[i][j]=true;
f[i][j]=f[i-1][j];
tmp[i][j]=tmp[i-1][j];
}
if(j-a[i].val<0) continue;
if(in[i-1][j-a[i].val])
{
nxt=f[i-1][j-a[i].val]+tmp[i-1][j-a[i].val]*a[i].p;
if(nxt>P-eps) continue;
if(!in[i][j])
{
in[i][j]=true;
f[i][j]=nxt;
tmp[i][j]=tmp[i-1][j-a[i].val]*(1-a[i].p);
}
else if(nxt<f[i][j])
{
f[i][j]=nxt;
tmp[i][j]=tmp[i-1][j-a[i].val]*(1-a[i].p);
}
}
}
for(int i=mx;i>=0;i--)
if(f[n][i]<P-eps && in[n][i])
{
ans=i;
break;
}
}
inline void print()
{
++cas;
printf("Case %d: %d\n",cas,ans);
}
int main()
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}