有 (n) 个订单,你可以选择接受其中的一部分。第 (i) 个订单要求你在 (t_i) 时刻输出 (g_i) 的商品,并获得 (m_i) 的收益。初态下你的生产力为 (1),每个单位时间你可以提高 (1) 的生产力或者以生产力的速度制造商品。求最大总收入。
(n leq 15, t_i leq 10^5)
Solution
看到 (nleq 15),想到暴力枚举接受哪些订单,并检验是否可行
考虑检验过程,设当前在考虑订单 (i) 到 (i+1) 的时间内花多少时间提高生产力
我们考虑暴力枚举 (i+1 o n),这里指的是所有选中了的订单,对于每个订单我们检查最多花多少时间提高生产力仍然能满足要求,然后在所有要求中取最小者即可
设完成订单 (i) 时的生产力为 (p),后续用来提高生产力的时间作为自变量 (x),(t) 为距离后续订单的时间,则
[(p+x)(t-x)=s
]
其中 (s) 为这一段的总需求量,解得
[x=frac1 2 (t-p+sqrt{(p+t)^2-4s})
]
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 35;
struct request {
int t,g,m;
bool operator < (const request &b) const {
return t<b.t;
}
} r[N],a[N];
int n;
int b[N],m,t[N],g[N];
int getans(int t,int p,int s) {
double x=0.5*(t-p+sqrt((p+t)*(p+t)-4*s));
return floor(x);
}
bool check() {
int prod=0, res=0;
for(int i=0;i<m;i++) {
int x=t[i+1]-t[i],s=-res;
for(int j=i+1;j<=m;j++) {
s+=a[j].g;
if(s<0) continue;
x=min(x,getans(t[j]-t[i],prod,s));
}
if(x<0) return 0;
prod+=x;
res+=(t[i+1]-t[i]-x)*prod;
res-=a[i+1].g;
if(res<0) {
return 0;
}
}
return 1;
}
signed main() {
cin>>n;
for(int i=1;i<=n;i++) {
cin>>r[i].t>>r[i].g>>r[i].m;
}
sort(r+1,r+n+1);
int ans=0;
t[0]=-1;
r[0].t=-1;
a[0].t=-1;
for(int i=0;i<1<<n;i++) {
for(int j=1;j<=n;j++) b[j]=(i>>(j-1))&1;
m=0;
int sum=0;
for(int j=1;j<=n;j++) if(b[j]) a[++m]=r[j], t[m]=a[m].t, g[m]=a[m].g, sum+=r[j].m;
if(check()) {
ans=max(ans,sum);
}
}
cout<<ans;
}