「题解」洛谷 P6893 [ICPC2014 WF]Buffed Buffet
对于离散的食物,\(w\) 相同的只留下美味值最大的 \(W/w\) 个,因为再多了也没用不会更优。所以一共只有 \(\sum_{i=1}^n \frac{W}{i}=\mathcal{O}(W\log n)\) 这样暴力背包复杂度就是 \(\mathcal{O}(W^2\log n)\).
然后考虑连续的怎么做。枚举离散的占了 \(w\) 的重量,那么离散的一定是先取不断吃最美味的,直到最美味的和次美味的一样好吃,这样这两个食物就可以看成一个了。加入其中两个 \(\Delta t\) 分别是 \(x,y\),稍微推推能推出新的食物的 \(\Delta t\) 为 \(\frac{xy^2+x^2y}{(x+y)^2}\).
所以总复杂度就是 \(\mathcal{O}(W^2\log n+Wn)\).
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<ctime>
#include<random>
#include<assert.h>
#define pb emplace_back
#define mp make_pair
#define fi first
#define se second
#define dbg(x) cerr<<"In Line "<< __LINE__<<" the "<<#x<<" = "<<x<<'\n';
#define dpi(x,y) cerr<<"In Line "<<__LINE__<<" the "<<#x<<" = "<<x<<" ; "<<"the "<<#y<<" = "<<y<<'\n';
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double ld;
typedef pair<int,int>pii;
typedef pair<ld,ld>pdd;
typedef pair<ll,int>pli;
typedef pair<ll,ll>pll;
typedef pair<int,ll>pil;
typedef vector<int>vi;
typedef vector<ll>vll;
typedef vector<pii>vpii;
typedef vector<pil>vpil;
template<typename T>T cmax(T &x, T y){return x=x>y?x:y;}
template<typename T>T cmin(T &x, T y){return x=x<y?x:y;}
template<typename T>
T &read(T &r){
r=0;bool w=0;char ch=getchar();
while(ch<'0'||ch>'9')w=ch=='-'?1:0,ch=getchar();
while(ch>='0'&&ch<='9')r=r*10+(ch^48),ch=getchar();
return r=w?-r:r;
}
template<typename T1,typename... T2>
void read(T1 &x,T2& ...y){read(x);read(y...);}
const int mod=998244353;
inline void cadd(int &x,int y){x=(x+y>=mod)?(x+y-mod):(x+y);}
inline void cdel(int &x,int y){x=(x-y<0)?(x-y+mod):(x-y);}
inline int add(int x,int y){return (x+y>=mod)?(x+y-mod):(x+y);}
inline int del(int x,int y){return (x-y<0)?(x-y+mod):(x-y);}
int qpow(int x,int y){
int s=1;
while(y){
if(y&1)s=1ll*s*x%mod;
x=1ll*x*x%mod;
y>>=1;
}
return s;
}
const int N=10010;
const ll inf=0x3f3f3f3f3f3f3f3f;
int n,m,W;
pdd lx[N],b[N];
vpii vec[N],ls;
ll f[N];
ld calc(pdd x,ld y){
return x.fi*y-0.5*x.se*y*y;
}
signed main(){
#ifdef do_while_true
// assert(freopen("data.in","r",stdin));
// assert(freopen("data.out","w",stdout));
#endif
read(n,W);
for(int i=1;i<=W;i++)f[i]=-inf;
for(int i=1;i<=n;i++){
int w,t,dt;
char c=getchar();while(c<'A'||c>'Z')c=getchar();
if(c=='D'){
read(w,t,dt);
vec[w].pb(mp(t,dt));
}
else{
read(t,dt);
lx[++m]=mp(t,dt);
}
}
sort(lx+1,lx+m+1,[](const pdd &x,const pdd &y){return x>y;});
for(int o=1;o<=W;o++)if(vec[o].size()){
vi a;
for(auto i:vec[o])
for(int j=1;j<=W/o;j++)
a.pb(i.fi-(j-1)*i.se);
nth_element(a.begin(),a.begin()+W/o,a.end(),[](const int &x,const int &y){return x>y;});
for(int i=0;i<W/o;i++)
for(int j=W;j>=o;j--)
if(f[j-o]!=-inf)
cmax(f[j],f[j-o]+a[i]);
}
if(m==0){
if(f[W]==-inf)puts("impossible");
else cout << f[W] << '\n';
return 0;
}
ld ans;
for(int o=0;o<=W;o++){
for(int i=1;i<=m;i++)b[i]=lx[i];
ld sum=f[o],rem=W-o;
for(int i=1;i<=m;i++){
if(i<m){
ld delta=(b[i].fi-b[i+1].fi)/b[i].se;
if(rem>delta){
sum+=calc(b[i],delta);
rem-=delta;
ld x=b[i].se,y=b[i+1].se;
b[i+1].se=(x*y*y+x*x*y)/((x+y)*(x+y));
}
else{
sum+=calc(b[i],rem);
break;
}
}
else sum+=calc(b[i],rem);
}
if(o==0)ans=sum;
else cmax(ans,sum);
}
printf("%.10lf\n",ans);
#ifdef do_while_true
cerr<<'\n'<<"Time:"<<1.0*clock()/CLOCKS_PER_SEC*1000<<" ms"<<'\n';
#endif
return 0;
}