1. 程式人生 > >P3161 [CQOI2012]模擬工廠

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;
}