AcWing3996 涂色

涂色

题意

给定一个长度为 \(n\) 的序列 \(a\) ,每次操作可以选择颜色相同的若干相邻元素,修改为任意数字,问最少修改几次使得序列 \(a\) 元素全部相同。

分析

区间DP,设 \(f(i, j)\) 表示将范围 \([i, j]\) 的元素修改成同一元素。

  1. 如果 \(a_i, a_j\) 元素相同,转移成将 \([i+1, j-1]\) 的元素修改为 \(a_i\)
  2. 如果 \(a_i, a_j\) 元素相同,考虑决策,把 \([i+1, j]\) 修改为 \(a_i\) 或者将 \([i, j-1]\) 修改为 \(a_j\) 。取 \(min\) 即可。

注意,我们需要把相同的元素(连通块)拼成一个同一个元素。

Code

#include <iostream>

using namespace std;

const int N = 5050;

int a[N], w[N], f[N][N];

int main ()
{
    int n, m = 0; cin >> n;
    for (int i = 1; i <= n; i ++ ) cin >> a[i];
    for (int i = 1; i <= n; i ++ ) if (a[i] != a[i-1]) w[++m] = a[i];
    for (int len = 2; len <= m; len ++ )
    {
        for (int l = 1; l + len - 1 <= m; l ++ )
        {
            int r = l + len - 1;
            if (w[l] != w[r]) f[l][r] = min(f[l+1][r], f[l][r-1]) + 1;
            else f[l][r] = f[l+1][r-1] + 1;
        }
    }
    cout << f[1][m] << endl;
    return 0;
}
posted @ 2021-11-20 13:16  Rainea  阅读(39)  评论(0)    收藏  举报