晚间测试2 A. 装饰 思维题
题目描述
分析
一道思维题
显然,\((a+b+c)/3\) 是答案的一个上界,\(a+b+c-max(a,b,c)\)也是答案的一个上
界,下面大致证明 \(min((a+b+c)/3,a+b+c-max(a,b,c))\)即为答案:
1、当\((a+b+c)/3 <= a+b+c-max(a,b,c)\)时,没有哪一种颜色的气球数量特别
地多,气球数量的差距可以将三色气球装饰的桌子更换一个气球来弥补,这样就
可以装饰\((a+b+c)/3\) 张桌子。
2、否则,不妨假设红色气球数量 \(a\) 很大,那么这时候显然可以装饰出 \(b+c=
a+b+c-max(a,b,c)\)张桌子(两个红色气球与一个非红色气球)。
综上所述,答案即为 \(min((a+b+c)/3,a+b+c-max(a,b,c))\)。
直接模拟放的过程也可以
代码(模拟)
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
inline int read(){
int x=0,fh=1;
char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') fh=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*fh;
}
int t,aa,bb,cc,cnt=0;
void msort(int &xx,int &yy,int &zz){
if(xx<yy) std::swap(xx,yy);
if(yy<zz) std::swap(yy,zz);
if(xx<yy) std::swap(xx,yy);
}
int main(){
freopen("decorate.in","r",stdin);
freopen("decorate.out","w",stdout);
t=read();
while(t--){
aa=read(),bb=read(),cc=read();
cnt=0;
while(1){
msort(aa,bb,cc);
if(aa==bb && bb==cc){
cnt+=aa;
break;
} else if(aa==bb+1 && bb==cc){
cnt+=cc;
break;
} else if(aa==bb && bb==cc+1){
cnt+=cc;
break;
}
if(aa<2 || bb<1) break;
if(aa!=bb){
if(bb==cc){
int now=std::min((aa-bb)/3,bb);
if(now==0){
aa-=2,bb--;
cnt++;
} else {
aa-=now*4;
bb-=now;
cc-=now;
cnt+=now*2;
}
} else {
int now=std::min(aa-bb,bb-cc);
aa-=now*2,bb-=now;
cnt+=now;
}
} else{
int now=(aa-cc)/3;
if(now==0 || aa<3){
aa-=2;
bb--;
cnt++;
} else {
aa-=now*3;
bb-=now*3;
cnt+=now*2;
}
}
}
printf("%d\n",cnt);
}
return 0;
代码(结论)
#include <cstdio>
#include <cstring>
#include <algorithm>
const int N = 1e6 + 10;
int main() {
freopen("decorate.in", "r", stdin);
freopen("decorate.out", "w", stdout);
int t;
scanf("%d", &t);
while(t--) {
long long a, b, c;
scanf("%lld%lld%lld", &a, &b, &c);
printf("%lld\n", std::min((a + b + c) / 3, a + b + c - std::max(a, std::max(b, c))));
}
return 0;
}