P3161 [CQOI2012]模拟工厂

传送门

先枚举选择哪些订单,然后转为判定是否可行
在能完成的情况下肯定是花越多时间提高生产力越优
我们设可以有\(x\)单位时间来提高生产力,那么如果当前离下一个订单的时间为\(T\)时,这个订单要\(P\)个产品,工厂拥有\(M\)的生产力时,显然有如下方程:

\[(M+x)*(T-x)=P(M+x)*(T-x)=P \]

整理之后得

\[x^2+(M-T)*x+P-M*T=0 \]

判断是否有解即可

//minamoto
#include<bits/stdc++.h>
#define ll long long
#define R register
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(R int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
inline int min(const R int &x,const R int &y){return x<y?x:y;}
inline int max(const R ll &x,const R ll &y){return x>y?x:y;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
    R int res,f=1;R char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
const int N=35;
struct node{
	int t,g,m;
	friend bool operator <(const R node &a,const R node &b){return a.t<b.t;}
}a[N],st[N];int top;
int n,t;ll ans,pp,gg,ss,res;
int calc(R ll k,R ll t,R ll g){
	ll a=1,b=k-t,c=g-k*t,del=b*b-4*a*c;
	return del<0?-1:((-b+sqrt(del))/2/a);
}
bool ck(){
	pp=1,gg=0;
	fp(i,1,top){
		ss=0,t=st[i].t-st[i-1].t;
		fp(j,i,top)if((ss+=st[j].g)>gg)t=min(t,calc(pp,st[j].t-st[i-1].t,ss-gg));
		if(t<0)return 0;
		pp+=t,gg+=pp*(st[i].t-st[i-1].t-t),gg-=st[i].g;
	}return 1;
}
int main(){
//	freopen("testdata.in","r",stdin);
	n=read();fp(i,1,n)a[i].t=read(),a[i].g=read(),a[i].m=read();
	sort(a+1,a+1+n);
	fp(i,1,(1<<n)-1){
		res=top=0;
		fp(j,1,n)if(i&(1<<(j-1)))st[++top]=a[j],res+=a[j].m;
		if(ck())ans=max(ans,res);
	}printf("%lld\n",ans);return 0;
}
posted @ 2018-12-06 13:50  bztMinamoto  阅读(106)  评论(0编辑  收藏  举报
Live2D