超级分类无敌边界 PK 简单分类强悍贪心 @ CodeForces 478C 题解
三种颜色的气球分别有R, G, B个, 每个桌子插三个气球, 每个桌子上的气球不能全是同一种颜色, 求能插多少个桌子.
这道题我在当时没写出来. 当时和原哥讨论, 首先是看错题以为是搜索, 后来看清题目后发现没那么复杂, 只需要贪心就可以. 然后我采用了原哥提出的这个贪心策略:
三种气球个数最多的减二, 次多的减一为一次操作. 能做多少次这样的操作, 答案就是多少次.
这是个正确的贪心策略, 我立马敲完代码交上去然后得到了 TLE. 这说明需要优化. 想到 A 题和 B 题都是用乘法优化加法, 难道今天是乘法优化专场, 于是我就想类似的用乘法优化. 这个想法引导我写了一个长长的程序, 把情况分为如下几类(假设 RGB 经过排序, R >= G >= B)
- R == G == B
- R == G > B
- R > G == B
- R > G > B
这样就有四个 (else) if 语句. 分类好了之后就是列出不等式, 计算乘法优化的那个乘数有多大. 这个过程耗费了我很多时间去 Debug, 修改不等式, 想特殊情况. 最后拿到了 Accepted. 这种方案的难点就是分类周全+边界考虑清楚. 代码如下:
/** * I love coding * @Author: Jecvay */ #include <iostream> using namespace std; inline int gint() {int n;scanf("%d", &n);return n;} int dfs(int a, int b, int c) { if (b < c) swap(b, c); if (a < b) swap(a, b); if (b < c) swap(b, c); int z = 0; if (a * b + a * c + b * c == 0) return 0; if (a == b && b == c || (a - b <= 2 && b == c) || (a == b && a - c <= 2)) { a -= c; b -= c; z = c; c = 0; if (z == 0) { if (a == 2) return 1; return 0; } z += dfs(a, b, c); } else if (a == b && b-c >= 3) { // -3 -3 0 ---> 2 int x = (b-c+2) / 3; x = min(x, b / 3); a -= 3 * x; b -= 3 * x; z = 2 * x + dfs(a, b, c); } else if (b == c && a-b >= 3) { // -4 -1 -1 ---> 2 int x = (a-b+2) / 3; x = min(x, a/4); x = min(x, b); a -= 4 * x; b -= x; c -= x; ast(a >= 0 && b >= 0 && c >= 0); z = 2 * x + dfs(a, b, c); } else { if (a > 1 && b > 0) { int x = min((a-c)/2, b-c); x = min(x, a-b); x = min(x, a/2); x = min(x, b); a -= 2 * x; b -= x; z = x + dfs(a, b, c); } } return z; } void solve() { int cnt = 0; cout << dfs(a[0], a[1], a[2]) << endl; } int main() { for (int i = 0; i < 3; i++) a[i] = gint(); solve(); return 0; }
既然 Accepted了, 就可以看看别人的代码怎么写的了, 不看不知道, 一看吓一跳, 代码如下:
int main() { cin >> a[0] >> a[1] >> a[2]; sort(a, a + 3); cout<<min((a[0] + a[1] + a[2]) / 3, a[0] + a[1]); }
两三行代码就搞定了. 这让我有点儿兴奋, 这是怎么做到的. 仔细想了一会, 原来是贪心策略就和我和原哥想的不一样. 这个贪心策略是这样的:
- 如果气球全用光了, 那么答案一定是所有气球的总数加起来除以三
- 如果气球没用光, 剩了一种颜色的气球A, 那么答案的个数则是其余两种气球个数之和 B + C, 原因就是每个桌子插两个A, 一个B, 或者两个A, 一个C, 这样耗到最后B和C都没了, 剩下A.
今天的经历非常好玩
我昨天有缘碰到这篇文章, 然后我就开窍了, 我感觉我做题再少都没问题, 但是不能再像以前一样依赖题解. 今天我尝试了一下, 自己思考得出了AC, 虽然解题方法不是最优, 但是思考了很多, 不看题解远比看题解要想得多, 训练程度高得多, 我喜欢这种感觉!
那种感觉就是, 题解不是写给不会做题的人看的, 是写给做出来题目的人看的, 用来在有了基础的情况下开阔眼界用的. 哎, 不过话是这么说, 世事难料, 不知道我能不看题解坚持做题到什么时候…