zoukankan      html  css  js  c++  java
  • 洛谷 题解 P3161 【[CQOI2012]模拟工厂】

    本蒟蒻又双叒叕被爆踩辣!

    题目链接

    Solution:

    这题又是一道贪心。。

    数据范围:

    n<=15 ti<=100,000 gi<=10^9 mi<=10^9
    

    这里就可以看到几个小细节,也可以想出一些思路。

    要开long long!

    首先,n <= 15, 这个数据可以说是很小辣,它代表有n个任务,又因为

    如果接受订单i,则必须恰好在时刻ti交易,不能早也不能晚。同一时刻可以接受多个订单,但每个订单只能被接受一次。
    

    窝们本不知道选择哪些任务才会是利润最高,而且这很明显也无法通过一些规律来知道选择哪个会最优。

    所以窝们应该怎么办???

    枚举!!!

    因为只有数据范围只有15,所以窝们可以枚举1到(1 << n) - 1用二进制表示当前这个任务选不选,那我们已经解决了这个任务辣!

    接下来就是,然后处理每个任务方案。

    窝们针对每个任务方案,依次判断它的可行性。

    然后在可行的方案中找出利润最大的(就是保证任务完成的情况下,保证生产力更大。

    假设窝们当前有那么对于订单i和j,我们都会得到方程:make为完成订单i时的生产力,time为距离j订单的时间,time_create为用来提升生产力的时间,need是订单j需求量

    (make + time_create) × (time − time_create) = need
    

    化简就是:

    time_create * time_create + (make - time) * time_create + need - make * time = 0;
    

    只要保证起“根的判别式” >= 0就行。

    所以复杂度应该是O(2 的 n次方 * n 的平方);

    具体见代码,这里只有一些思路,个人介意对着代码读,更容易理解

    Code:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define maxn 25
    #define maxm
    #define ll long long//mi数据1e9,你不开longlong看看 
    #define int long long
    #define Rep(x, a, b) for(int x = a; x <= b; ++ x)
    #define Dep(x, a, b) for(int x = a; x >= b; -- x)
    #define Next(x, u) for(int i = head[u]; i ; i = e[i].nxt)
    
    //int read(){窝不喜欢用快读,但缺省源里面放了,所以也没删 
    //	int f = 1, x = 0;
    //	char c = getchar();
    //	while(c < '0' || c > '9'){
    //	if(c == '-'){
    //	f = -1;
    //	}
    //	c = getchar();
    //	}
    //	while(c >= '0' && c <= '9'){
    //	x = (x << 1) + (x << 3) + (c ^ 48);
    //	c = getchar();
    //	}
    //	return x * f;
    //}
    
    struct node{
    int t, g, m;//都如题,t是在什么时刻交易,g是需要多少货,m是可以得到的利润 
    }e[maxn], s[maxn];
    
    //e是记录所有的任务
    //s是记录当前情况窝们已经选择的任务 
    
    int n, ans;//不多说
    
    bool cmp(node x, node y){
    return x.t < y.t;
    }//要先按照t排序,要不不好处理
    
    int discriminant(int b, int c){//这个单词是“判别式”,百度说的
    if(b * b - 4 * c < 0){//都知道二次函数根的判别式吧(b * b - 4 * a * c) 
    return -1;//返回-1,即根的判别式小于0 
    }
    return floor((-b + sqrt(b * b - 4 * c)) / 2);//否则就返回它的根:((-b + sqrt(b * b - 4 * a * c) / 2 / a) 
    }
    
    void dfs(int x){
    int now_have = 0, make_force = 1, ans_now = 0, tot = 0;
    //now_have是窝们当前拥有的货物
    //make_force是当前的生产力
    //ans_now是这种方案的利润 
    //tot是当前这种选择方案任务的个数 
    Rep(i, 1, n){//这里就是寻找当前方案的任务 
    if(x & (1 << i - 1)){//用二进制 
    s[++ tot] = e[i];//进入s 
    ans_now += e[i].m;//就是当前方案的总利润 
    }
    }
    Rep(i, 1, tot){
    int t = s[i].t - s[i - 1].t, sum = 0;//sum是所需要的货物 
    //t是时间,s[i].t - s[i- 1].t是它的最大值,因为当它前面的货物足够购买这两个货物时,它的t就是此值 
    Rep(j, i, tot){//算t的值 
    sum += s[j].g;//累加所需要的货物 
    if(now_have >= sum){//如果货物还够,那就下一层循环 
    continue;
    }//否则,就更新t,为t,和它的根的最小值 
    t = min(t, discriminant(make_force - s[j].t + s[i - 1].t, sum - now_have - make_force * (s[j].t - s[i - 1].t)));
    }
    if(t < 0){//如果无法完成次方案 
    return;//return 
    }
    make_force += t;//生产力就要加,(尽可能加就行 
    now_have += make_force * (s[i].t - s[i - 1].t - t) - s[i].g;//其余就现在有的产量 
    }
    ans = max(ans, ans_now);//更新值 
    }
    
    signed main(){
    scanf("%lld", &n);//输入 
    Rep(i, 1, n){//输入每个任务 
    scanf("%lld%lld%lld", &e[i].t, &e[i].g, &e[i].m);
    }
    sort(e + 1, e + n + 1, cmp);//按时刻排序 
    Rep(i, 0, (1 << n) - 1){
    dfs(i);//每种方案跑一遍 
    }
    printf("%lld", ans);//输出 
    return 0;
    }
    

    下面还给两组数据

    Inout:
    5
    5 5 5
    7 7 7
    9 9 9
    11 1 15
    16 18 778
    
    Output:
    814
    
    
    Input:
    10
    1 1 1
    2 2 2
    3 3 3
    4 4 4
    5 5 5
    6 6 6
    7 7 7
    8 8 8
    9 9 9
    10 10 10
    
    Output:
    30
    

    Ps:请看懂再抄

  • 相关阅读:
    Java实现 蓝桥杯 历届试题 小计算器
    事实证明,应用市场是个流量的生意(产品能力并不足以形成护城河)
    迅雷创始人程浩:创业公司5招做好内部创新(组建小型敢死队:一共3个人,一个产品经理,两个研发;腾讯做不做这个项目是一个伪命题;让用户来验证,而不是相反 good)
    核心思想:创业者要做正确的决定,而非容易的决定(享受创业路上的孤单,你必须要有将自己关在小屋子里独自做重大且艰难决定的勇气)
    Delphi能通过SSH登录Linux,连接MYSQL取数么?像Navicat一样
    Qt5.7中使用MySQL Driver(需要把libmysql.dll文件拷贝到Qt的bin目录中。或者自己编译的时候,链接静态库)
    c++对象内存布局的理解
    观察者模式
    本地事务和分布式事务工作
    弱引用
  • 原文地址:https://www.cnblogs.com/Flash-plus/p/12028242.html
Copyright © 2011-2022 走看看