LUOGU P3161 [CQOI2012]模拟工厂 (贪心)

Posted sdfzsyq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LUOGU P3161 [CQOI2012]模拟工厂 (贪心)相关的知识,希望对你有一定的参考价值。

传送门

解题思路

贪心,首先因为(n)比较小,可以(2^n)枚举子集。然后判断的时候就每次看后面的如果用最大生产力生产能不能达成目标,解一个二次函数。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define int long long
 
using namespace std;
const int MAXN = 25;
typedef long long LL;

inline int rd(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {f=ch==‘-‘?0:1;ch=getchar();}
    while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();}
    return f?x:-x;
}

int n,t[MAXN],g[MAXN],m[MAXN],cnt,mk[MAXN],ans;
int tmp[MAXN];

inline bool cmp(int x,int y){
    return t[x]<t[y];
}

int calc(int a,int b,int c){
    double delta=b*b-4*a*c;
    if(delta<0) return -1;
    return floor((-b+sqrt(delta))/(a*2));
}

inline bool check(){
    for(int i=1;i<=cnt;i++) tmp[i]=mk[i];
    sort(tmp+1,tmp+1+cnt,cmp);
    int tt,now=1;LL sum=0,res=0;
    for(int i=1;i<=cnt;i++){
        sum=0;tt=t[tmp[i]]-t[tmp[i-1]];
        for(int j=i;j<=cnt;j++){
            sum+=g[tmp[j]];
            if(sum>res)
                tt=min(tt,calc(1,now-t[tmp[j]]+t[tmp[i-1]],
                sum-res-now*(t[tmp[j]]-t[tmp[i-1]])));
        }
        if(tt<0) return false;
        now+=tt;res+=(now*(t[tmp[i]]-t[tmp[i-1]]-tt)-g[tmp[i]]);
    }
    return true;
}

void dfs(int x,LL sum){
    if(x==n+1) {if(sum>ans) if(check()) ans=sum;return;}
    mk[++cnt]=x;dfs(x+1,sum+m[x]);
    cnt--;dfs(x+1,sum);
}

signed main(){
//  freopen("data.txt","r",stdin);
//  freopen("B.txt","w",stdout);
    n=rd();
    for(int i=1;i<=n;i++) t[i]=rd(),g[i]=rd(),m[i]=rd();
    dfs(1,0);cout<<ans;
    return 0;
}

以上是关于LUOGU P3161 [CQOI2012]模拟工厂 (贪心)的主要内容,如果未能解决你的问题,请参考以下文章

p3159 [CQOI2012]交换棋子

[BZOJ2667][cqoi2012][kcoj]模拟工厂

[CQOI2012]交换棋子(最小费用最大流)

[Luogu 2261] CQOI2007 余数求和

「luogu4462」[CQOI2018]异或序列

luogu3168 [CQOI2015]任务查询系统