BZOJ 4073 Wf2014 Buffed Buffet 斜率优化

来源:互联网 发布:2000年人口普查数据 编辑:程序博客网 时间:2024/03/29 07:13

题目大意:给定d种食物,食物分两个类型:离散食物和连续食物
离散食物只能按份供应,每种食物有一个质量w
连续食物可以食用任意质量
每种食物有一个初始美味值t和一个美味值衰减系数t
对于一种离散食物,如果你吃了N份,那么获得的美味值为Ni=1(t(i1)t)
对于一种连续食物,如果你吃的质量为X,那么获得的美味值为X0(txt)dx
现在你必须吃总质量为W的食物,求最多获得的美味值(可以为负),无解输出”impossible”
d250,W104,0t,t104

由于W104,我们可以考虑枚举离散食物吃多少,然后将离散食物和连续食物分开考虑

对于离散食物,我们令fi表示吃质量为i的离散食物能获得的最大美味值
枚举每种食物更新fi,有DP方程:
fi=fj+(2t(ijw1)t)ijw2(0ji,ij(mod w))
把这个式子化简可以斜率优化,于是离散食物就可以求了

对于连续食物,显然我们要用贪心的思想来吃
将所有连续食物按照t从大到小排序,首先我们肯定要吃最大的
随着最大的食物的美味值在不断下降,总有一时刻这种食物的美味值会和第二大的一样
这时候我们显然要把两种食物混合着吃,那么我们不妨将这两种食物合并成一种美味值衰减系数为11t1+1t2的食物
然后继续吃下去就行了

时间复杂度O(dWlog2W)

注意BZ上的数据精度不够 用long double会挂掉一个点

#include <cstdio>#include <cstring>#include <iomanip>#include <iostream>#include <algorithm>#define M 10100#define EPS 1e-7#define INF 1e30using namespace std;typedef double ld;int n,m;long long f[M];pair<double,double> stack[300];int top;double sum[M];bool able[M];namespace Convex_Hull{    struct Point{        long long x,y;        Point() {}        Point(long long _,long long __):            x(_),y(__) {}        friend double Get_Slope(const Point &p1,const Point &p2)        {            return (double)(p1.y-p2.y)/(p1.x-p2.x);        }    }stack[M];int top;    double slope[M];    void Initialize()    {        top=0;    }    void Insert(const Point &p)    {        double s=top?Get_Slope(stack[top],p):0;        while( top>=2 && -slope[top]<s )            s=Get_Slope(stack[--top],p);        stack[++top]=p;slope[top]=-s;    }    Point Query(double s)    {        return stack[lower_bound(slope+2,slope+top+1,-s-EPS)-slope-1];    }}void Slope_Optimized_DP(long long w,long long t,long long dt){    static long long g[M];    int i,j;    long long _i;    memset(g+1,0,sizeof(g[0])*m);    for(i=0;i<w;i++)    {        Convex_Hull::Initialize();        for(j=0;(_i=i+j*w)<=m;j++)        {            if(able[_i])                Convex_Hull::Insert( Convex_Hull::Point( j , 2*f[_i] - dt*j*j - 2*t*j ) );            if(!Convex_Hull::top)                g[_i] = 0xefefefefefefefefll;            else             {                long long _j = Convex_Hull::Query( - (2*j-1)*dt ).x;                g[_i] = f[i+_j*w] + ( 2*t - ( (j-_j)-1 ) * dt ) * ( j-_j ) / 2 ;            }        }    }    for(i=w;i<=m;i++)        able[i]|=able[i-w];    memcpy(f+1,g+1,sizeof(f[0])*m);}/*void Unoptimized_DP(long long w,long long t,long long dt){    int i,j;    for(i=1;i*w<=m;i++)        for(j=m;j>=w;j--)            if(able[j-w])                f[j]=max(f[j],f[j-w]+t-(i-1)*dt);    for(i=w;i<=m;i++)        able[i]|=able[i-w];}*/int main(){    int i,j,w,t,dt;    char p[10];    cin>>n>>m;    memset(f,0xef,sizeof f);f[0]=0;able[0]=true;    for(i=1;i<=n;i++)    {        scanf("%s",p);        if(p[0]=='D')        {            scanf("%d%d%d",&w,&t,&dt);            Slope_Optimized_DP(w,t,dt);            //Unoptimized_DP(w,t,dt);        }        else        {            scanf("%d%d",&t,&dt);            stack[++top]=pair<double,double>(t,dt);        }    }    if(!top)    {        if(!able[m])            puts("impossible");        else            cout<<f[m]<<".000000000"<<endl;        return 0;    }    sort(stack+1,stack+top+1);    double l=0,r=0,slope=INF,sum=0;    for(i=1;i<=top>>1;i++)        swap(stack[i],stack[top-i+1]);    for(j=1,i=1;i<=top;i++)    {        slope=1.0/(1.0/slope+1.0/stack[i].second);        l=r;r=i==top||slope<EPS?m+1:l+(stack[i].first-stack[i+1].first)/slope;        for(;j<=r+EPS&&j<=m;j++)            ::sum[j]=sum+(j-l)*(stack[i].first*2-(j-l)*slope)/2;        sum+=(r-l)*(stack[i].first*2-(r-l)*slope)/2;        if(slope<EPS) break;    }    double ans=-INF;    for(i=0;i<=m;i++)        if(able[i])            ans=max(ans,f[i]+::sum[m-i]);    cout<<fixed<<setprecision(9)<<ans<<endl;    return 0;}
0 0