题目大意
从任意一个位置开始,将与这个位置上数字相同的数字改变成任意的数字,最后使所有数字都相同,问最少需要多少次。
解题思路
数据量很明显可以用(n^2)做法,我们先让所有连续相同的数字都变成一个,方便转移。考虑区间dp,设dp[l][r]为区间[l,r]的最少代价,如果两端字符相同,那么它就能从子区间dp[l+1][r-1]转移过来,否则的话,有两种可能,可能是从[l+1,r]转移过来的,也可能是[l,r-1],取最优即可。由于我们之前把连续相同的数字都改成了一个,所以相邻的数字必不相同,每次的转移代价都需要+1。
代码
const int maxn = 5e3+10;
const int maxm = 2e5+10;
int dp[maxn][maxn], a[maxn], b[maxn], n, m;
int main() {
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]) b[++m] = a[i];
for (int len = 1; len<=m; ++len)
for (int l = 1; l+len<=m; ++l) {
int r = l+len;
if (b[l]==b[r]) dp[l][r] = dp[l+1][r-1]+1;
else dp[l][r] = min(dp[l+1][r], dp[l][r-1])+1;
}
cout << dp[1][m] << endl;
return 0;
}