题目大意:给定
离散食物只能按份供应,每种食物有一个质量w
连续食物可以食用任意质量
每种食物有一个初始美味值
对于一种离散食物,如果你吃了
对于一种连续食物,如果你吃的质量为
现在你必须吃总质量为
由于
对于离散食物,我们令
枚举每种食物更新
把这个式子化简可以斜率优化,于是离散食物就可以求了
对于连续食物,显然我们要用贪心的思想来吃
将所有连续食物按照
随着最大的食物的美味值在不断下降,总有一时刻这种食物的美味值会和第二大的一样
这时候我们显然要把两种食物混合着吃,那么我们不妨将这两种食物合并成一种美味值衰减系数为
然后继续吃下去就行了
时间复杂度
注意BZ上的数据精度不够 用long double会挂掉一个点
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define M 10100
#define EPS 1e-7
#define INF 1e30
using 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;
}
BZOJ 4073 Wf2014 Buffed Buffet 斜率优化
原文地址:http://blog.csdn.net/popoqqq/article/details/46045271