晚間測試2 A. 裝飾 思維題
阿新 • • 發佈:2020-10-05
題目描述
分析
一道思維題
顯然,\((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; }