现在的位置: 首页 > 综合 > 正文

CF 478C – Table Decorations(贪心+想法)

2018年04月04日 ⁄ 综合 ⁄ 共 1067字 ⁄ 字号 评论关闭

刷刷题别让智商掉太快。

题目链接: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;
}

抱歉!评论已关闭.