[贪心 二次函数] BZOJ 2667 [cqoi2012]模拟工厂

本文介绍了一种通过状压枚举来优化生产力提升与产品制造平衡的算法策略。该方法利用二次函数特性求解最优生产力提升时间,确保订单按时完成。通过递归枚举所有可能的订单组合,并判断是否满足条件,最终找出最大利润。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

跪Po姐

状压枚举
每次Check的时候,对于每段时间显然先提高生产力再生产产品 
那么我可以考虑这一段内先尽量提高生产力 但是这样可能会导致生产力提高得太高而没有足够的时间生产产品使得某个订单失败 
因此我们计算出对于后面的每一个订单,最多花多少时间提高生产力可以满足如果用接下来的时间都生产的话不至于fail 
由于产品数量是关于提高生产力次数的二次函数 因此解个方程就行了


#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;

inline char nc()
{
    static char buf[100000],*p1=buf,*p2=buf;
    if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
    return *p1++;
}

inline void read(ll &x)
{
    char c=nc(),b=1;
    for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
    for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const ll N=25;

struct abcd{
    ll t,g,m;
    void read(){
        ::read(t); ::read(g); ::read(m);
    }
    bool operator < (const abcd &B) const{
        return t<B.t;
    }
}s[N],a[N];
ll tot;

ll n;
ll w,g,t,x;

inline ll Calc(double a,double b,double c){
    double delta=b*b-4*a*c;
    if (delta<0) return -1;
    double x1,x2;
    x1=(-b-sqrt(delta))/a/2; x2=(-b+sqrt(delta))/a/2;
    if (x1>x2) swap(x1,x2);
    return floor(x2);
}

inline bool Jud()
{
    w=1; g=0;
    for (int i=1;i<=tot;i++)
    {
        x=t=a[i].t-a[i-1].t;
        ll tem=0;
        for (int j=i;j<=tot;j++)
        {
            tem+=a[j].g;
            if (tem>g)
                x=min(x,Calc(-1,(a[j].t-a[i-1].t)-w,(a[j].t-a[i-1].t)*w+g-tem));
        }
        if (x<0) return 0;
        g+=(w+=x)*(t-x);
        g-=a[i].g;
    }
    return 1;
}

int main()
{
    ll ans=0,tmp=0;
    freopen("t.in","r",stdin);
    freopen("t.out","w",stdout);
    read(n);
    for (int i=1;i<=n;i++)
        s[i].read();
    sort(s+1,s+n+1);
    for (int i=0;i<(1<<n);i++)
    {
        tmp=tot=0;
        for (int j=1;j<=n;j++)
            if (i&(1<<(j-1)))
                tmp+=s[j].m,a[++tot]=s[j];
        if (Jud())
            ans=max(ans,tmp);
    }
    printf("%lld\n",ans);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值