[BZOJ2667][cqoi2012]模拟工厂 贪心

2667: [cqoi2012]模拟工厂

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 367  Solved: 184
[Submit][Status][Discuss]

Description

有一个称为“模拟工厂”的游戏是这样的:在时刻0,工厂的生产力等于1。在每个时刻,你可以提高生产力或者生产商品。如果选择提高生产力,在下一个时刻时工厂的生产力加1;如果选择生产商品,则下一个时刻你所拥有的商品数量增加p,其中p是本时刻工厂的生产力。
n个订单,可以选择接受或者不接受。第i个订单(tigimi)要求在时刻ti给买家提供gi个商品,事成之后商品数量减少gi,而收入增加mi元。如果接受订单i,则必须恰好在时刻ti交易,不能早也不能晚。同一时刻可以接受多个订单,但每个订单只能被接受一次。要求最后的总收入最大。
例如,如果一共有两个订单(5,1,8)和(7,15,3),用如下策略是最优的:时刻0, 1, 2提高生产力(时刻3的生产力为4),然后在时刻3,4生产商品,则在时刻5时将拥有8个商品。此时接受第1个订单(还会剩下7个商品),并且在时刻5,6继续生产商品,则在时刻7时拥有7+4+4=15个商品,正好满足订单2。

Input

输入第一行包含一个整数n,即订单数目。以下n行每行三个整数tigimi
 

Output

 
输出仅一行,为最大总收入。输出保证在32位带符号整数范围内。

Sample Input

2
5 1 8
7 15 3

Sample Output

11

HINT

 




































编号


1-3


4-6


7-10


n


<=5


<=10


<=15


ti


100


100


<=100,000


gi


10,000


10,000


<=109


mi


10,000


10,000


<=109

 

 

Source

考虑贪心,显然每一段先加生产力再生产。

枚举订单后n*n check。

check时我们设当前工作力为g,天数为t,现在剩余a

则得方程(g+x)(t-x)>=a+需求。可解出能够增加生产力的天数。

联立方程,可得若干个区间[l,r]。显然取最小的r作为增加生产力的天数。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 #define ll long long
 8 using namespace std;
 9 ll n;
10 struct data {
11     ll tim,g,m;
12     bool operator <(const data tmp)const {
13         return tim<tmp.tim;
14     }
15 }t[20];
16 int q[20],tot;
17 ll gets(ll a,ll b,ll c) {
18     ll de=b*b-4*a*c;if(de<0) return -1;
19     double d=sqrt(de);
20     double x1=(-b-d)/(2.0*a),x2=(-b+d)/(2.0*a);
21     return max((ll)floor(x1),(ll)floor(x2));
22 }
23 ll ans=0;
24 void solve(int x) {
25     ll sum=0;tot=0;
26     for(int i=1;i<=n;i++) if((1<<(i-1))&x) q[++tot]=i; 
27     ll s=0,g=1;
28     for(int i=1;i<=tot;i++) {
29         ll tmp=2147483647ll,now=0;
30         for(int j=i;j<=tot;j++) {
31             now+=t[q[j]].g;
32             ll b=t[q[j]].tim-t[q[i-1]].tim;
33             tmp=min(tmp,gets(-1,b-g,b*g+s-now));
34             if(tmp<0) {sum=0;return;}
35         }
36         g+=tmp;s+=g*(t[q[i]].tim-t[q[i-1]].tim-tmp);sum+=t[q[i]].m;s-=t[q[i]].g;
37     }
38     ans=max(ans,sum);
39 }
40 int main() {
41     scanf("%lld",&n);
42     for(int i=1;i<=n;i++) scanf("%lld%lld%lld",&t[i].tim,&t[i].g,&t[i].m);
43     sort(t+1,t+n+1);
44     for(int i=0;i<=(1<<n)-1;i++) solve(i);
45     printf("%lld",ans);
46 }
View Code

 

posted @ 2018-02-09 13:30  wls001  阅读(218)  评论(0编辑  收藏  举报