题目描述:
牛牛有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 )
扫描二维码关注公众号,回复:
9862318 查看本文章
可以看出两个式子取个最小值,相等的时候 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;
}