牛客练习赛59 C.装备合成(三分)

题目描述:

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

输入描述:

输入包含t组数据
第一行一个整数t
接下来t行每行两个整数x,y

输出描述:

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

输入

5
4 8
7 6
8 10
100 4555
45465 24124

输出

2
2
3
50
13917

1<=t<=10000
1<=x,y<=1e9

本题让你求出制作装备的最大数量,枚举用第一种方案制作装备的数量t1( 0<=t1<=min(x/2,y/3) ), 则第二种方案制作的数量t2为 min( (x-2 * t1 )/4, y-3 * t1 )
我们就是求的 t1 + t2 = t1 + min( (x-2 * t1 )/4, y-3 * t1 )的最大值

如果我们直接暴力枚举 O(1e9/2) TLE

我们可以利用二分或者三分

二分适用,单调
二分适用,单调或者图像是一个抛物线(二次函数)

我们分析 t1 + min( (x-2 * t1 )/4 , y-3 * t1 ) =min( (2 * t1 +x)/4 , y-2 * t1 )

可以看出两个式子取个最小值,相等的时候 t1=(4*y-x)/4,他是有极值的,我们并不知道极值的取值在不在t1的范围内,所以我们利用三分查找缩小范围,最后暴力求一个小范围的遍历。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<set>
#include<sstream>
using namespace std;
typedef long long ll;
const ll maxn=1e6+10;
const ll inf=0x3f3f3f3f3f3f3f3f;
ll solve(ll t1,ll x,ll y)//第二件装备个数 
{
    return min((x-2*t1)/4,y-3*t1);
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    ll t;
    cin>>t;
    while(t--)
    {
        ll a,b;
        cin>>a>>b;
        ll l=0,r=min(a/2,b/3);//三分找第一种装备件数
        while(l<r)
        {
            ll lm=l+(r-l)/3;
            ll rm=r-(r-l)/3;
            if(l==lm&&r==rm) break;//防止死循环
            if(lm+solve(lm,a,b)<=rm+solve(rm,a,b))
                l=lm;
            else
                r=rm;
        } 
        ll ans=0;
        for(int i=l;i<=r;i++)
        {
            ans=max(ans,i+solve(i,a,b));
        }
        cout<<ans<<endl;
     } 
    return 0;
}
发布了88 篇原创文章 · 获赞 30 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43667611/article/details/104893506
今日推荐