[CC LEBOXES]buy

来源:互联网 发布:淘宝网商城女装上衣 编辑:程序博客网 时间:2024/04/29 07:02

题目大意

n个袋子,第i个袋子有pi几率装有vi金钱,否则装有一颗宝石。
有m个食物,第i个食物需要ci的金钱和di颗宝石,求最优情况下,期望买下食物个数。

折半

宝石个数不超过n。
设f[i,j]表示买下i个食物使用了至多j颗宝石最少花费的钱,可以dp出来。
然后对于袋子,我们折半搜索,先搜索前半部分,并根据宝石数分段,每段按照金钱排序,并统计概率前缀和。
然后搜索后半部分,假如搜出的状态是(v,d,p)代表有v的金钱d颗宝石,发生该场面的概率为p。
枚举前半部分获得的宝石数t以及最终买下的食物个数i。
假设前半部分的金钱为g,那么要有
f[i,t+d]<=v+g

#include<cstdio> #include<algorithm>#include<cstring>#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--) using namespace std;typedef double db;const int maxn=30+10,inf=1000000000;int f[maxn][maxn],v[maxn],c[maxn],d[maxn],ll[maxn],rr[maxn];struct dong{    int v,d;    db p;} a[1000000];db p[maxn],sum[1000000],ans;int i,j,k,l,r,t,n,m,mid,top,ca;void dfs(int x,int y,int z,db q){    if (x==mid+1){        a[++top].v=y;        a[top].d=z;        a[top].p=q;        return;    }    dfs(x+1,y+v[x],z,q*p[x]);    dfs(x+1,y,z+1,q*(1-p[x]));}void work(int v,int d,db p){    int i,t,j,k,l,r,x,y,mid;    fo(i,1,n)        fo(t,0,n){            if (!ll[t]) continue;            j=f[i][t+d]-v;            k=f[i+1][t+d]-v;            if (j>0&&j<1000){                l=l;            }            if (a[rr[t]].v<j||a[ll[t]].v>=k) continue;            l=ll[t];r=rr[t];            while (l<r){                mid=(l+r)/2;                if (a[mid].v>=j) r=mid;else l=mid+1;            }            x=l;            l=ll[t];r=rr[t];            while (l<r){                mid=(l+r+1)/2;                if (a[mid].v<k) l=mid;else r=mid-1;            }            y=l;            ans=ans+(sum[y]-sum[x-1])*i*p;        }}void dg(int x,int y,int z,db q){    if (x==n+1){        work(y,z,q);        return;    }    dg(x+1,y+v[x],z,q*p[x]);    dg(x+1,y,z+1,q*(1-p[x]));}bool cmp(dong a,dong b){    return a.d<b.d||(a.d==b.d&&a.v<b.v);}int main(){    //freopen("t2.in","r",stdin);freopen("t2.out","w",stdout);    scanf("%d",&ca);    while (ca--){        scanf("%d%d",&n,&m);        fo(i,1,n){            scanf("%d%d",&v[i],&t);            p[i]=(db)t/100;        }        fo(i,1,m) scanf("%d%d",&c[i],&d[i]);        memset(f,127/2,sizeof(f));        fo(i,0,n) f[0][i]=0;        fo(i,1,m)            fd(j,m,1)                fo(l,d[i],n) f[j][l]=min(f[j][l],f[j-1][l-d[i]]+c[i]);        mid=n/2;        top=0;        dfs(1,0,0,1);        sort(a+1,a+top+1,cmp);        fo(i,0,n) ll[i]=0;        ll[a[1].d]=1;        fo(i,2,top)            if (a[i].d!=a[i-1].d){                rr[a[i-1].d]=i-1;                ll[a[i].d]=i;            }        rr[a[top].d]=top;        sum[0]=0;        fo(i,1,top) sum[i]=sum[i-1]+a[i].p;        ans=0;        dg(mid+1,0,0,1);        printf("%.4lf\n",ans);    }}
0 0
原创粉丝点击