题目描述
今天是某不愿透露姓名的谈姓大佬的生日,转发这场比赛到三个群就可以,获得以下三种礼包之一。
豪华礼包:一个U盘、一个鼠标和一个机械键盘。
幸运礼包:一个U盘、两个鼠标。
普通礼包:两个U盘、一个鼠标。
大佬一共准备了a个U盘、b个鼠标和c个机械键盘。为了给更多的人带来足够多的惊喜,大佬希望相邻的两位领礼包的参赛选手拿到的礼包类型都是不同的。
由于大佬正在宴请Final选手,并没有空打理这些,所以想让你告诉他 这些奖品最多可以发出多少份礼包。
输入描述:
输入第一行包含一个正整数T。
接下来T行每行包含3个正整数a, b, c,依次表示U盘、鼠标和机械键盘各有多少个。
输出描述:
输出T行,每行一个整数,表示最多能发出多少份礼包。
示例1
输入
2
4 4 0
1 1 1
输出
2
1
备注:
T<=100000
0<=a,b,c<=1000000
思路:由题可以知道每份礼物中都有a和b,当每份礼物去除掉一个a和b之后
豪华礼包:剩余c ,幸运礼包:剩余b ,普通礼包:剩余a
利用二分的方法寻找可以送出多少份礼包。
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
bool pd(int a,int b,int c,int mid){
//因为每份礼物都有a和b mid份礼物就要减去mid个a和b
a-=mid;
b-=mid;
if(a<0||b<0){ //减完后a或b有一个小于0,则不能发出mid份礼物
return false;
}
if(a+b+c<mid){//减完后 a+b+c的个数要大于等于 mid份礼物
return false;
}
//选出a b c的值中选最小的两个 用a和b表示
if(a>b)swap(a,b);
if(b>c)swap(b,c);
//保证不相邻 则小的两个之和要大于等于mid/2
if(a+b<mid/2) return false;
return true;
}
int main(){
int T;
int a,b,c;
scanf("%d",&T);
for(int i=0;i<T;i++){
scanf("%d %d %d",&a,&b,&c);
int l=0,r=min(a,b); //因为每份礼物都要用到一个a和一个b,这里取a和b中小的那个
int k,mid;
//二分查找礼物的个数
while(l<=r){
mid=l+(r-l)/2;
if(pd(a,b,c,mid)){
k=mid;
l=mid+1;
}
else{
r=mid-1;
}
}
printf("%d\n",k);
}
return 0;
}