题解:P14294 [JOI2024 预选赛 R2] 白色灯 2 / White Light 2

· · 题解

给出一个只含有 \texttt{R}, \texttt{G}, \texttt{B} 的字符串 S(|S| = n),你可以执行任意次以下操作:

你需要使操作后的字符串 S 满足以下任意一种要求:

*** 显然动态规划。先不考虑第二种操作。 令 $F_i(C)$ 为只考虑前 $i$ 个字符,处理后末尾字符为 $C$ 的最小代价。 显然我们有 $$ \left\{ \begin{aligned} &F_i(\texttt{NULL}) &&= F_{i - 1}(\texttt{NULL}) + A \\ &F_i(\texttt{R}) &&= \min\{F_{i-1}(\texttt{NULL}), F_{i-1}(\texttt{B})\} + W(S_i \to \texttt{R}) \\ &F_i(\texttt{G}) &&= F_{i-1}(\texttt{R}) + W(S_i \to \texttt{G}) \\ &F_i(\texttt{B}) &&= F_{i-1}(\texttt{G}) + W(S_i \to \texttt{B}) \end{aligned} \right. $$ 其中 $W(A \to B)$ 是代价增量函数,$W(A \to B) = C \times [A = B]$。 加入第二种操作,答案就是 $\min\limits_{i=1}^n \left\{F_i(\texttt{B}) + (n - i)B\right\}$ 和 $\min\limits_{i=0}^n \left\{F_i(\texttt{NULL}) + (n - i)B\right\}$ 的较小值。 时间复杂度 $O(n)$,空间复杂度 $O(n)$。 ::::success[代码] ```cpp void solve() { i64 n, a, b, c, ans = inf64; std::string s; std::cin >> n >> s >> a >> b >> c, s = ' ' + s; std::vector f(2, std::vector(5, inf64)); // 0 = NULL, 1 = R, 2 = G, 3 = B; f[0][0] = 0; ans = n * b; for (i32 i = 1; i <= n; i++) { std::fill(f[i & 1].begin(), f[i & 1].end(), inf64); f[i & 1][0] = f[i & 1 ^ 1][0] + a; f[i & 1][1] = std::min(f[i & 1 ^ 1][0] + c * (s[i] != 'R'), f[i & 1][1]); f[i & 1][1] = std::min(f[i & 1 ^ 1][3] + c * (s[i] != 'R'), f[i & 1][1]); f[i & 1][2] = std::min(f[i & 1 ^ 1][1] + c * (s[i] != 'G'), f[i & 1][2]); f[i & 1][3] = std::min(f[i & 1 ^ 1][2] + c * (s[i] != 'B'), f[i & 1][3]); ans = std::min({ans, f[i & 1][3] + (n - i) * b, f[i & 1][0] + (n - i) * b}); } std::cout << ans << endl; return void(); } ``` ::::