题目大意:
所以Conan要前往专卖店买东东,专卖店正在搞促销,有三种礼包:
①豪华礼包:一个U盘、一个鼠标、一个机械键盘。
②幸运礼包:一个U盘、两个鼠标。
③普通礼包:两个U盘、一个鼠标。
卖店内准备了a个U盘、b个鼠标和c个机械键盘。为了给顾客带来足够多的惊喜,店长希望相邻两位领礼包的顾客拿到的礼包类型都是不同的。店长想知道这些奖品最多可以发出多少份礼包。可是店长毕竟没有Conan聪明,所以请教Conan,可是Conan要急着回去打游戏,所以就交给你啦,有T次请教。
对于30%的数据满足T<=10,a,b,c<=30。
对于60%的数据满足T<=100,a,b,c<=300,000。
对于100%的数据满足t<=100000,0<=a,b,c<=1000,000。
题解:
二分:
思路:
因为答案最多也就min(a,b)之间,即最大为1000000,所以二分答案!
然后答案可能=0,所以l=0,r赋值一个比较大的值,不知道为什么直接赋值min(a,b)就错了。。。
如果你当前的答案是l了,你就要判断l+1是否小于r,不小于就停止二分,当前的答案已经是最优解了。
因为每种礼包最多用1 U盘,1鼠标,所以我们对于当前二分到的Mid,
普通礼包可以买x =a-mid,
幸运礼包可以买y =b-mid,
豪华礼包可以买z =c
若x>=0 y>=0 则进一步判断:
x+y+z>=mid 保证能买mid个
因为礼包不能相邻所以任意一种不能超过答案的一半:
x+y>=mid/2 z不能超过mid的一半
x+z>=mid/2 同理判断y
y+z>=mid/2 同理判断x
时间复杂度:O(20*T)
…2^20>100000…
var
t,a,b,c,i,l,r,mid,x,y,z,xy:longint;
begin
readln(t);
for i:=1 to t do
begin
readln(a,b,c);
l:=0; r:=1000000;
while l+1<r do
begin
mid:=(l+r) div 2;
xy:=mid div 2;
x:=a-mid; y:=b-mid; z:=c;
if (x>=0) and (y>=0) and (x+y+z>=mid) and
(x+y>=xy) and (x+z>=xy) and (y+z>=xy)
then l:=mid
else r:=mid;
end;
writeln(l);
end;
end.