刷刷题别让智商掉太快。
题目链接:Click here~~
题意:
给三种颜色的球,分别有不同的数量,现在需要将他们每三个球分成一组,分组条件是同组的球颜色不能完全相同,问最多可以分成多少组。
思路:
感觉做过一道类似的题目,一看数据范围就不用想其他做法了,直接贪心策略搞吧。想来想去还是这样讲比较有说服力:
先考虑颜色只有两种 {A,B} 时的情况,此时组合只能是 <1A,2B>,<2A,1B> 这种方式。
为了有尽可能多的组,我们要保证当其中一种球用完时,另一种球剩下的个数尽可能少。
先假设个数 A < B,那么肯定是球 A 更可能先用完,所以我们更倾向于选择 <1A,2B> 的组合方式,这样会使 A,B 的差值逐步缩小,直到相等。
当 A == B 以后,每次交替使用 <1A,2B> 和 <2A,1B>,即可以通过 <3A,3B> 的方式构造两组解从而一直维持这种相等的趋势,直到 A 和 B 的个数小于3。
之后,A + B < 6,此时理论上能构造的组数已经小于 2 组,所以只需要判断 A,B 中是否还能构成一组即可,其实也就是判断 A,B 是否为 2。
下面说颜色为 {A,B,C} 时的情况,同样假设 A < B < C。
类似的,我们应该尽可能让 A 用完的时候,B 和 C 的差值尽量小,这样可以使最后剩余一种的那个球个数最少,即浪费最少。
最后的策略顺序是这样的,先尽量用 <1A,2C> 消耗过多的 C,然后用 <1A,1B,1C> 将 A 消耗完且不增加 B,C 的差距,后面就变成了 {A',B'} 的情况,按上述策略玩就好了。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int main() { int cnt[3]; for(int i = 0; i < 3; ++i) { scanf("%d", &cnt[i]); } sort(cnt, cnt + 3); int ans = 0; int k1 = min(cnt[0], (cnt[2] - cnt[1]) / 2); cnt[0] -= k1; cnt[2] -= k1 * 2; int k2 = cnt[0]; cnt[0] -= k2; cnt[1] -= k2; cnt[2] -= k2; int k3 = min(cnt[1], cnt[2] - cnt[1]); cnt[1] -= k3; cnt[2] -= k3 * 2; int k4 = cnt[1] / 3 * 2; cnt[1] -= k4 / 2 * 3; cnt[2] -= k4 / 2 * 3; int k5 = ((cnt[1] == 1 && cnt[2] >= 2) || cnt[1] == 2) ? 1 : 0; ans = k1 + k2 + k3 + k4 + k5; printf("%d\n", ans); return 0; }