装备合成 三分

题目链接

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

题目描述

在这里插入图片描述

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



解析

使用三分的使用一定要注意要么这是个二次函数,要么这是个分段的凹凸函数,千万不能把两条斜率不同但作用域重合了的直线合并出来的函数盲目的看成一个凹凸函数
本题其实也可以对极值点的两边分别二分求最优解

证明

设:以2a,3b方式合成的装备有m件 以4a,b方式合成的装备有n件

m取值范围为 0 ~ min(x/2,y/3),
合成的装备总数就是
F(m) = m + min((x-2,)/4,y-3m);

为分段函数,拆掉min得到
F(m) = (x+2m)/4, m <= (4y -x)/10;
F(m) = y - 2m ,m > (4y - x)/10;

函数F(m)中x,y为常数,所以F(m)关于m从左到右先增后减,为凸函数,所以可以对函数F(m)使用三分


三分算法使用技巧

这里有一个三分的技巧,考虑到整数除法的小数丢失,所以你最后得到的是近似点,可能不是真正的极值点,但它一定非常靠近极值点,这时你只要枚举一下近似点的附近的那几个点就行

code

#include<bits/stdc++.h>
using namespace std;
int main(){
    int T;    cin >> T;
    while(T--){
        int x,y;    cin >> x >> y;
        int l,r,m1,m2;
        l = 0; r = min(x/2,y/3);
       
        while(l < r){
            m1 = l + (r - l)/3;
            m2 = r - (r - l)/3;
            int ans1 = m1 + min( (x - 2 * m1)/4, y - m1 * 3);
            int ans2 = m2 + min( (x - 2 * m2)/4, y - m2 * 3);
            
            if(ans1 >= ans2)
                r = m2 - 1;
            else l = m1 + 1;
        }
        
        int ans = 0;
        int ma = min(x/2,y/3);
        
        for(int i = max(0,l - 3) ; i <= min(l + 3,ma); ++i)//枚举近似点范围的所有点
            ans = max(ans,i + min( (x - i * 2)/4, y - i * 3));
        cout << ans << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值