第19节 装备合成
牛牛有件材料和件材料,用件材料和件材料可以合成一件装备,用件材料和件材料也可以合成一件装备。牛牛想要最大化合成的装备的数量,于是牛牛找来了你帮忙。
输入描述:
输入包含组数据
第一行一个整数
接下来行每行两个整数
输出描述:
每组数据输出一行一个整数表示答案。
示例1
输入
5
4 8
7 6
8 10
100 4555
45465 24124
输出
2
2
3
50
13917
备注:
三分:
假设第一种装备合成了m件,那么第二种装备可以合成min((x-2m)/4,y-3m)件;那么总共的装备个数就是:m+min((x-2m)/4,y-3m);
可以证明当 (x-2m)/4<y-3m 时单增,反之单减;所以是个单峰凸函数;可以对m进行三分;(m的最大值是min(x/2,y/2))
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll t,x,y;
ll get(ll m)
{
return m+min((x-2*m)/4,y-3*m);
}
int main()
{
cin>>t;
while(t--)
{
scanf("%lld%lld",&x,&y);
ll l=0,r=min(x/2,y/3);//右端点很严格,变化了就过不了,是全部用于第一种方案得到的个数
while(l<r)
{
ll m1=l+(r-l)/3;
ll m2=r-(r-l)/3;
if(get(m1)>get(m2)) r=m2-1;
else l=m1+1;
}
cout<<get(l)<<endl;
}
}
贪心的思路
思路:贪心的尽量选第一种方案,设第一种方案用了k1次,第二种方案用了k2次,那么方程就是2k1+4k2=x,3k1+k2=y,那么就有10k1=4y-x,关键这里k1不一定是整数,所以k1这里要四舍五入并且要和x/2和y/3比较取最小值。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ll x,y,k1;
scanf("%lld%lld",&x,&y);
k1=4*y-x;
if(k1<0){
printf("%d\n",y);continue;
}
k1=(k1+5)/10;
k1=min(x/2,k1),k1=min(y/3,k1);
x-=2*k1,y-=3*k1;
printf("%lld\n",k1+min(x/4,y));
}
}