卧薪尝胆,厚积薄发。
CQOI2012 模拟工厂
Date: Wed Aug 19 11:05:18 CST 2020
In Category:
NoCategory
Description
一个工厂每一时刻可以提高
$1$
生产力或者生产商品,
$n$
个订单给出时间,数量,收益,问最大收益。
$1\leqslant n\leqslant15$
Solution
首先
$2^n$
枚举选哪个订单,然后判断是否可行。
从第一个订单开始,状态可以用剩余存量
$rem$
和生产力
$pro$
表示,如果当前是第
$i$
个订单,
$i-1$
到
$i$
之间时间为
$t$
,那么枚举
$j$
从
$i$
到
$n$
,对于
$i$
到
$j$
这一段都应该是满足总量的,对于
$j$
,因为
$i\sim j-1$
是已经满足了的,所以我们可以看成这些量都在
$j$
的时刻,这样也不会影响对于总量是否合法的判断,这些量总量为
$sum$
,若加生产力所需时间为
$x$
,那么有
$(t-x)\times (pro+x)+rem\geqslant sum$
即
$x^2+x\times(p-t)+s-r-t\times p\leqslant0$
,可以解得
$x$
的区间为
$[l_j,r_j]$
,这时总量满足了,但无法判断之后生产的速度能否满足,因此要让
$pro$
尽可能大,选最大的
$\lfloor r_j\rfloor$
中的最小值即可。
Code
#include<bits/stdc++.h>
using namespace std;
int n;
#define MAXN 20
#define LL long long
#define INF 0x3f3f3f3f3f3f3f3f
struct query
{
LL t,g,m;
}q[MAXN];
bool cmp(query a,query b){return a.t < b.t;}
bool sel[MAXN];
int s[MAXN],tot;
long long ans = 0;
LL calc(LL t,LL pro,LL rem,LL sum)//x^2+x*(p-t)+s-r-t*p<=0
{
LL a = 1,b = pro - t,c = sum - rem - t * pro;
LL delta = b * b - 4 * a * c;
if(delta < 0)return -1;
return (-b + sqrt((double)delta)) / 2;
}
void solve()
{
tot = 0;
for(int i = 1;i <= n;++i)if(sel[i])s[++tot] = i;
LL pro = 1,rem = 0;
for(int i = 1;i <= tot;++i)
{
LL sum = 0,t = q[s[i]].t - q[s[i - 1]].t;
LL x = INF;
for(int j = i;j <= tot;++j)
{
sum = sum + q[s[j]].g;
x = min(x,calc(q[s[j]].t - q[s[i - 1]].t,pro,rem,sum));
}
if(x < 0)return;
pro += x;
rem = rem + (t - x) * pro - q[s[i]].g;
}
LL res = 0;
for(int i = 1;i <= tot;++i)res += q[s[i]].m;
ans = max(ans,res);
return;
}
void dfs(int pos)
{
if(pos == n + 1){solve();return;}
sel[pos] = true;dfs(pos + 1);
sel[pos] = false;dfs(pos + 1);
return;
}
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;++i)scanf("%lld%lld%lld",&q[i].t,&q[i].g,&q[i].m);
sort(q + 1,q + 1 + n,cmp);
dfs(1);
cout << ans << endl;
return 0;
}
In tag:
算法-贪心
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡