P3161 [CQOI2012] 模拟工厂
题意
一个工厂,之生产一种产品,每个时刻两种操作:增加生产力和生产当前生产力大小个产品。
现在有 \(n\) 个订单 \((t_i,g_i,m_i)\),表示如果在 \(t_i\) 时刻上交 \(g_i\) 个零件,那么获得 \(m_i\) 收益,任何时刻产品数量不能为负。问最大收益。
\(n\le15,t_i\le10^5,g_i,m_i\le10^9\)。
思路
发现 \(n\) 很小,暴力枚举每个订单是否要被完成,问题转化为判断是否可以在第一些时刻获得大于某个值得物品数量。
从前往后遍历订单,设当前遍历到第 \(i\) 个订单,已经生产 \(ng\) 个产品,当前生产力为 \(pw\),现在考虑时刻 \(t_i\) 到 \(t_{i+1} 的操作\)。设这段时间增加了 \(x\) 点生产力,令 \(T=t_{i+1}-t_i\),那么需要满足 \(\forall j>i,(T-x)(pw+x)\ge-ng\sum_{k=i+1}^{j}g_k\),这个 \(x\) 才有可能合法。枚举 \(j\),对于每个 \(j\),把满足条件的最大 \(x\) 求出来,如果不存在,直接判断不可行。在这些最大的 \(x\) 中取最小,即限制最严格的那个,把祂作为 \(t_i\) 到 \(t_{i+1}\) 增加的生产力。
时间复杂度 \(\mathcal O(2^nn^2)\)。
代码
// Problem: P3161 [CQOI2012] 模拟工厂
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3161
// Memory Limit: 125 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
namespace IO{
template<typename T>
inline void read(T&x){
x=0;char c=getchar();bool f=0;
while(!isdigit(c)) c=='-'?f=1:0,c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
f?x=-x:0;
}
template<typename T>
inline void write(T x){
if(x==0){putchar('0');return ;}
x<0?x=-x,putchar('-'):0;short st[50],top=0;
while(x) st[++top]=x%10,x/=10;
while(top) putchar(st[top--]+'0');
}
inline void read(char&c){c=getchar();while(isspace(c)) c=getchar();}
inline void write(char c){putchar(c);}
inline void read(string&s){s.clear();char c;read(c);while(!isspace(c)&&~c) s+=c,c=getchar();}
inline void write(string s){for(int i=0,len=s.size();i<len;i++) putchar(s[i]);}
template<typename T>inline void write(T*x){while(*x) putchar(*(x++));}
template<typename T,typename...T2> inline void read(T&x,T2&...y){read(x),read(y...);}
template<typename T,typename...T2> inline void write(const T x,const T2...y){write(x),putchar(' '),write(y...),sizeof...(y)==1?putchar('\n'):0;}
}using namespace IO;
#define LL long long
const int maxn=20;
int n;
struct node{
int t,g,m;
bool operator<(const node ano)const{return t<ano.t;}
}a[maxn],use[maxn];
LL calc(LL pw,LL ti,LL mb){//(pw+x)(ti-x)=mb
LL a=1,b=pw-ti,c=mb-1LL*pw*ti;
LL derta=b*b-4*a*c;
if(derta<0) return -1;
return (LL)((-b+sqrt(derta))/(2.0*a));
}
bool check(int st){
int cnt=0;
for(int i=1;i<=n;i++) if(st&(1<<i-1)) use[++cnt]=a[i];
LL pw=1,ng=0;
for(int i=0;i<cnt;i++){
LL p=0,add=1000000000;
for(int j=i+1;j<=cnt;j++){
p+=use[j].g;
LL x=calc(pw,use[j].t-use[i].t,p-ng);
if(x<0) return 0;
add=min(add,x);
}
pw+=add;
ng+=(use[i+1].t-use[i].t-add)*pw;
ng-=use[i+1].g;
}
return 1;
}
signed main(){
read(n);
for(int i=1;i<=n;i++) read(a[i].t,a[i].g,a[i].m);
LL ans=0;
sort(a+1,a+1+n);
for(int i=1;i<(1<<n);i++){
LL sum=0;
for(int j=1;j<=n;j++) if(i&(1<<j-1)) sum+=a[j].m;
if(sum>ans&&check(i)) ans=sum;
}
write(ans);
return 0;
}

浙公网安备 33010602011771号