题目大意
题面总结
给定多组数据。每组给出三种幽火数量:红色 r、绿色 g、蓝色 b。
你需要构造一个只由 R、G、B 组成的字符串 s,表示按顺序摆放的幽火颜色,要求:
如果有多个最长可行答案,输出任意一个即可。
输入输出要求
-
输入第一行为测试组数 t。
-
每组输入一行三个整数 r g b。
-
对每组输出一行构造出的字符串 s。
数据范围
样例
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 输入 5 0 0 1 1 1 1 0 3 0 2 2 2 2 7 3
输出 B RGB G GBRBRG GRGRGBGBGBG
|
样例配合说明
-
第 1 组:只有 1 个蓝色,输出 B,长度为 1 且合法。
-
第 2 组:三种颜色各 1 个,RGB 使用了全部 3 个且满足限制。
-
第 3 组:只有绿色 3 个,但相邻不能同色,所以最多只能放 1 个,输出 G。
-
第 4 组:GBRBRG 长度为 6,刚好把 2,2,2 全部用完,并满足相邻与间隔 2 的限制。
-
第 5 组:GRGRGBGBGBG 在给定数量下给出一个满足条件的最长构造。
思路讲解

不难发现,能够凑的话,肯定是凑出足够的这个 gb,gr,rb 最好。但是怎么样凑出最多的 gb,gr,rb?其实这个就是求解一个线性方程组(如上),我们可以得到 rb 的这个数量。
但你会发现,如果采用数学式方法,去求解这个二元组的数量,然后去做,肯定是能做出来的,但是坑非常多,首先,这个元组是有可能 rb 求出来是一个负数。
这道题目怎么做?如下。

当然,你说为什么就强制给他安一个前缀就对了?其实也没什么神秘的,其实到最后,就是一个奇偶性问题,奇偶性问题有的时候一个的改变,就足以改变正确性了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| for (int i = 0; i < pow3[3]; ++i) { ll opi = i; vector<Num_color> rgb = rgb_global; string ans; auto push_to_ans = [&](ll i) { ans.push_back(rgb[i].color); rgb[i].num--; }; auto check_ans = [&]() { for (int i = SZ(ans) - 1; i >= SZ(ans) - 2; --i) { if (i - 1 < 0) { break; } if (ans[i] == ans[i - 1]) { return false; } } for (int i = SZ(ans) - 1; i >= SZ(ans) - 2; --i) { if (i - 3 < 0) { break; } if (ans[i] == ans[i - 3]) { return false; } } return true; }; auto check_ans_all = [&]() { for (int i = SZ(ans) - 1; i >= 0; --i) { if (i - 1 < 0) { break; } if (ans[i] == ans[i - 1]) { return false; } } for (int i = SZ(ans) - 1; i >= 0; --i) { if (i - 3 < 0) { break; } if (ans[i] == ans[i - 3]) { return false; } } return true; }; while (opi != 0) { push_to_ans(opi % 3); opi/=3; } if (!check_ans_all()) { continue; } sort(all(rgb), cmp); if (rgb[2].num < 0) { continue; } while (true) { sort(all(rgb), cmp); if (rgb[2].num > 0) { push_to_ans(0); push_to_ans(2); if (!check_ans()) { swap(ans[SZ(ans) - 1], ans[SZ(ans) - 2]); if (!check_ans()) { break; } } continue; } if (rgb[1].num > 0) { push_to_ans(0); push_to_ans(1); if (!check_ans()) { swap(ans[SZ(ans) - 1], ans[SZ(ans) - 2]); if (!check_ans()) { break; } } continue; } if (rgb[0].num > 0) { push_to_ans(0); if (!check_ans()) { ans.pop_back(); break; } } break; } if (SZ(ans) > SZ(ans_global)) { swap(ans, ans_global); } } cout << ans_global << "\n";
|
AC代码
AC
https://codeforces.com/contest/2209/submission/367802322
源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
|
#include <bits/stdc++.h> #define all(vec) vec.begin(),vec.end() #define lson(o) (o<<1) #define rson(o) (o<<1|1) #define SZ(a) ((long long) a.size()) #define debug(var) cerr << #var <<" = ["<<var<<"]"<<"\n"; #define debug1d(a) \ cerr << #a << " = ["; \ for (int i = 0; i < (int)(a).size(); i++) \ cerr << (i ? ", " : "") << a[i]; \ cerr << "]\n"; #define debug2d(a) \ cerr << #a << " = [\n"; \ for (int i = 0; i < (int)(a).size(); i++) \ { \ cerr << " ["; \ for (int j = 0; j < (int)(a[i]).size(); j++) \ cerr << (j ? ", " : "") << a[i][j]; \ cerr << "]\n"; \ } \ cerr << "]\n"; #define cend cerr<<"\n-----------\n" #define fsp(x) fixed<<setprecision(x)
using namespace std;
using ll = long long; using ull = unsigned long long; using DB = double; using i128 = __int128; using CD = complex<double>;
static constexpr ll MAXN = (ll) 1e6 + 10, INF = (1ll << 61) - 1; static constexpr ll mod = 998244353; static constexpr double eps = 1e-8; const double pi = acos(-1.0);
ll lT, testcase;
struct Num_color { ll num; char color; };
bool cmp(const Num_color &a, const Num_color &b) { return a.num > b.num; }
void Solve() { vector<Num_color> rgb_global(3); cin >> rgb_global[0].num >> rgb_global[1].num >> rgb_global[2].num; rgb_global[0].color = 'R'; rgb_global[1].color = 'G'; rgb_global[2].color = 'B';
string ans_global;
vector<ll> pow3(30); pow3[0] = 1; for (int i = 1; i <= 25; ++i) { pow3[i] = pow3[i - 1] * 3; }
for (int i = 0; i < pow3[3]; ++i) { ll opi = i; vector<Num_color> rgb = rgb_global; string ans; auto push_to_ans = [&](ll i) { ans.push_back(rgb[i].color); rgb[i].num--; }; auto check_ans = [&]() { for (int i = SZ(ans) - 1; i >= SZ(ans) - 2; --i) { if (i - 1 < 0) { break; } if (ans[i] == ans[i - 1]) { return false; } } for (int i = SZ(ans) - 1; i >= SZ(ans) - 2; --i) { if (i - 3 < 0) { break; } if (ans[i] == ans[i - 3]) { return false; } } return true; }; auto check_ans_all = [&]() { for (int i = SZ(ans) - 1; i >= 0; --i) { if (i - 1 < 0) { break; } if (ans[i] == ans[i - 1]) { return false; } } for (int i = SZ(ans) - 1; i >= 0; --i) { if (i - 3 < 0) { break; } if (ans[i] == ans[i - 3]) { return false; } } return true; }; while (opi != 0) { push_to_ans(opi % 3); opi/=3; } if (!check_ans_all()) { continue; } sort(all(rgb), cmp); if (rgb[2].num < 0) { continue; } while (true) { sort(all(rgb), cmp); if (rgb[2].num > 0) { push_to_ans(0); push_to_ans(2); if (!check_ans()) { swap(ans[SZ(ans) - 1], ans[SZ(ans) - 2]); if (!check_ans()) { break; } } continue; } if (rgb[1].num > 0) { push_to_ans(0); push_to_ans(1); if (!check_ans()) { swap(ans[SZ(ans) - 1], ans[SZ(ans) - 2]); if (!check_ans()) { break; } } continue; } if (rgb[0].num > 0) { push_to_ans(0); if (!check_ans()) { ans.pop_back(); break; } } break; } if (SZ(ans) > SZ(ans_global)) { swap(ans, ans_global); } } cout << ans_global << "\n";
#ifdef LOCAL vector<Num_color> rgb_back = rgb_global; for (int i = 0; i < SZ(ans_global) - 1; ++i) { if (ans_global[i] == ans_global[i + 1]) { cout << "NO\n"; cout << "WA ON " << i << "\n"; return; } } for (int i = 0; i < SZ(ans_global) - 3; ++i) { if (ans_global[i] == ans_global[i + 3]) { cout << "NO\n"; cout << "WA ON " << i << "\n"; return; } } string brute; auto dfs = [&](auto &&go, string s) -> void { if (SZ(s) > SZ(brute)) { brute = s; } for (int i = 0; i < 3; ++i) { if (rgb_back[i].num >= 1) { if (SZ(s) >= 1) { if (s.back() == rgb_back[i].color) { continue; } } if (SZ(s) >= 3) { if (s[SZ(s) - 3] == rgb_back[i].color) { continue; } } rgb_back[i].num--; go(go, s + rgb_back[i].color); rgb_back[i].num++; } } }; dfs(dfs, ""); if (SZ(brute) != SZ(ans_global)) { cout << "too small\n"; cout << brute << "\n"; } #endif }
signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); #ifdef LOCAL cout.setf(ios::unitbuf); #endif
cin >> lT; for (testcase = 1; testcase <= lT; ++testcase) Solve(); return 0; }
|
心路历程(WA,TLE,MLE……)
写对拍器的时候,为了防止对拍写的有问题,最好写为不等于,这样子,对拍器生成的字符串过小也可以非常容易的看出来。
1 2 3 4 5
| dfs(dfs, ""); if (SZ(brute) != SZ(ans)) { cout << "too small\n"; cout << brute << "\n"; }
|