• 牛客练习赛 59 c 装备合成


    链接:https://ac.nowcoder.com/acm/contest/4743/C
    来源:牛客网

    题目描述:

    牛牛有x件材料a和y件材料b,用2件材料a和3件材料b可以合成一件装备,用4件材料a和1件材料b也可以合成一件装备。牛牛想要最大化合成的装备的数量,于是牛牛找来了你帮忙。

    输入描述:

    输入包含t组数据

    第一行一个整数t

    接下来t行每行两个整数x,y

    输出描述:

    每组数据输出一行一个整数表示答案。

    朴素做法:

    发现 三件甲和一件乙,共花费10件x, 10件b,所以可以通过这个去凑,最后朴素枚举当x、y不够10件的情况

    #include <bits/stdc++.h>
    using namespace std;
     
    const int maxn = 1e5 + 5;
     
    int a, b, t;
     
    int main()
    {
         scanf("%d", &t);
         while (t--)
         {
             scanf("%d%d", &a, &b);
             int ansa = 0, ansb = 0;
             if (a >= b)
             {
                 int t = min(b, (a - b) / 3);
                 b -= t, a -= t << 2;
                ansb = t + b / 10, ansa = b / 10 * 3;
                 a -= b / 10 * 10, b %= 10;
             }
             else
             {
                 int t = min(a >> 1, b - a);
                 b -= 3 * t, a -= t << 1;
                 ansb = a / 10, ansa = t + a / 10 * 3;
                 b -= (a / 10) * 10, a %= 10;
             }
             if (a >= 4 && b > 0)
             {
                 int t = min(a >> 2, b);
                 ansb += t, a -= t << 2, b -= t;
             }
             if (a >= 2 && b >= 3)
             {
                 int t = min(a >> 1, b / 3);
                 ansa += t, a -= t << 1, b -= t * 3;
             }
             if (b == 0)
                 while (ansa && a >= 6)
                 {
                     --ansa, a += 2, b += 3;
                     int t = min(a >> 2, b);
                     ansb += t, a -= t << 2, b -= t;
                 }
             else if (b)
                 while (ansb && b >= 5)
                 {
                     --ansb, b += 1, a += 4;
                     int t = min(a >> 1, b / 3);
                     ansa += t, a -= t << 1, b -= t * 3;
                 }
             printf("%d", ansa + ansb);
             if (t) puts("");
         }
         return 0;
    }
    

      

    三分做法:

    假设做n件甲,那么做$min(frac{x - 2 * n}{4},y - 3 * n)$件乙
    总件数$all = n + min(frac{x - 2 * n}{4},y - 3 * n)$,求all的最大值
    一般的就是把n枚举,但是从题目x,y<=1e9
    n=[0,min(x/2,y/3)]——即完全不做甲 ->完全做甲,时间复杂度是1e9/2
    所以我们要用三分缩小n的范围,然后在范围内枚举n
    把all看出是关于自变量n的函数,$all=n+min(frac{x - 2 * n}{4},y - 3 * n)$
    三分用之前一定要验证函数是$wedge$或$vee$或单增或单减的函数,即h(x)'在范围内最多一个零点
    然而想一下,x、y差不多的时候($wedge$), x远远大于y的时候(单增),y远远大于x的时候(单减)
    每次看两个三分之一点哪个更小,更小的更新为边界
     
    #include <bits/stdc++.h>
    using namespace std; 
    const int maxn = 1e5 + 5; 
    
    int a, b, t;
     
    int is(int n)
    {
         return n + min((a - 2 * n) >> 2, b - 3 * n);
    }
     
    int main()
    {
         scanf("%d", &t);
         for (int i=0;i<t;i++)
         {
             scanf("%d%d", &a, &b);
             int l = 0, r = min(a / 2, b / 3);
             while (r - l > 3)
             {
                 int m1 = l + (r - l) / 3, m2 = r - (r - l) / 3;
                 if (is(m1) > is(m2)) r = m2;
                 else l = m1;
             }
             int ans = 0;
             while (l <= r) ans = max(ans, is(l++));
             printf("%d
    ", ans);
         }
         return 0;
    }
    

      

  • 相关阅读:
    makefile中宏定义
    make的静态模式
    makefile中两重if判断
    定义命令包
    嵌套执行make
    AcWing 1014. 登山
    AcWing 482. 合唱队形
    AcWing 1027. 方格取数
    AcWing 1016. 最大上升子序列和
    AcWing 187. 导弹防御系统
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/12493783.html
Copyright © 2020-2023  润新知