[CQOI2012] 模拟工厂

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

原文地址:https://www.cnblogs.com/mollnn/p/12651961.html