BZOJ 2667 cqoi2012 模拟工厂 贪心

来源:互联网 发布:淘宝订单接口 编辑:程序博客网 时间:2024/06/17 05:39

题目大意:现在你有一个工厂,初始生产力为1,每一时刻你可以进行如下操作:
1.将生产力提高1
2.生产一些产品,数量等于当前生产力的数值
现在你有n个订单,每一份有一个交易时间t,一个商品数量g和一个价格m,可以接或者不接,如果接就要在t时刻操作之前减少g的商品数量,然后得到m的钱
求最大收益

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

#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define M 20using namespace std;struct abcd{    int tim,goods,money;    friend istream& operator >> (istream &_,abcd &a)    {        return scanf("%d%d%d",&a.tim,&a.goods,&a.money),_;    }    bool operator < (const abcd &a) const    {        return tim < a.tim ;    }}a[M],stack[M];int n,top;long long ans;int Calculate(long long k,long long t,long long g){    long long a=1,b=k-t,c=g-k*t;    long long delta=b*b-4*a*c;    if(delta<0)        return -1;    return (long long)(floor( (-b+sqrt(delta))/2/a +1e-7 )+1e-7);}bool Judge(){    int i,j;    long long productivity=1,_goods=0;    for(i=1;i<=top;i++)    {        long long sum=0;        int _tim=stack[i].tim-stack[i-1].tim;        for(j=i;j<=top;j++)        {            sum+=stack[j].goods;            if(sum>_goods)                _tim=min(_tim, Calculate(productivity,stack[j].tim-stack[i-1].tim,sum-_goods) );        }        if(_tim<0)            return false;        productivity+=_tim;        _goods+=productivity*(stack[i].tim-stack[i-1].tim-_tim);        _goods-=stack[i].goods;    }    return true;}int main(){    int i,j;    cin>>n;    for(i=1;i<=n;i++)        cin>>a[i];    sort(a+1,a+n+1);    for(i=1;i<1<<n;i++)    {        long long _money=0;        top=0;        for(j=1;j<=n;j++)            if(i&(1<<j-1))                stack[++top]=a[j],_money+=a[j].money;        if( Judge() )            ans=max(ans,_money);    }    cout<<ans<<endl;    return 0;}
0 0
原创粉丝点击