专栏文章

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

P14294题解参与者 4已保存评论 3

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
3 条
当前快照
1 份
快照标识符
@minj7rtf
此快照首次捕获于
2025/12/02 03:18
3 个月前
此快照最后确认于
2025/12/02 03:18
3 个月前
查看原文
给出一个只含有 R,G,B\texttt{R}, \texttt{G}, \texttt{B} 的字符串 S(S=n)S(|S| = n),你可以执行任意次以下操作:
  • 把第一个字符删去,代价为 AA
  • 把最后一个字符删去,代价为 BB
  • 修改任意一个字符,代价为 CC
你需要使操作后的字符串 SS 满足以下任意一种要求:
  • S=0|S| = 0
  • Smod3=0|S| \bmod 3 = 00iS31,S3i+1=R,S3i+2=G,S3i+3=B\forall 0 \le i \le \dfrac{|S|}{3} - 1, S_{3i+1} = \texttt{R}, S_{3i+2} = \texttt{G}, S_{3i+3} = \texttt{B}
1n2×105,1A,B,C1091 \le n \le 2 \times 10^5, 1 \le A, B, C \le 10^9

显然动态规划。先不考虑第二种操作。
Fi(C)F_i(C) 为只考虑前 ii 个字符,处理后末尾字符为 CC 的最小代价。
显然我们有
{Fi(NULL)=Fi1(NULL)+AFi(R)=min{Fi1(NULL),Fi1(B)}+W(SiR)Fi(G)=Fi1(R)+W(SiG)Fi(B)=Fi1(G)+W(SiB)\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(AB)W(A \to B) 是代价增量函数,W(AB)=C×[A=B]W(A \to B) = C \times [A = B]
加入第二种操作,答案就是 mini=1n{Fi(B)+(ni)B}\min\limits_{i=1}^n \left\{F_i(\texttt{B}) + (n - i)B\right\}mini=0n{Fi(NULL)+(ni)B}\min\limits_{i=0}^n \left\{F_i(\texttt{NULL}) + (n - i)B\right\} 的较小值。
时间复杂度 O(n)O(n),空间复杂度 O(n)O(n)
代码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();
}

评论

3 条评论,欢迎与作者交流。

正在加载评论...