视频题解戳我
题目大意:选择一个初始点,同色的为一个块,每一次可以将包含起始点块的左或右的那个方块变色,问最少操作次数。
解题思路:对数据已经存在的同色块,留一个就好了,不影响结果。考虑若是1 2 3 4,都是不同色的,那要操作size-1次3次;若有1 2 1这种类似回文的,那就操作一次就行了,所有我们求出序列中最长的回文子序列长度/2 ,那就是我们可以节省的操作次数,我们可以将原序列倒序再和原序列求一个最长公共子序列即可。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<cmath>
#include<sstream>
using namespace std;
typedef long long ll;
const int maxn = 5e3+5;
vector<int> fir;
vector<int> sec;
int dp[maxn][maxn];
int main() {
std::ios::sync_with_stdio(0);
int n;
cin >> n;
int tp;
while (n--) {
cin >> tp;
if (fir.empty() || fir.back() != tp)
fir.push_back(tp);
}
sec = fir;
reverse(sec.begin(), sec.end());
fir.insert(fir.begin(), 0); //为方便多插入了个0
sec.insert(sec.begin(), 0);
for (int i = 1; i < (int)fir.size(); ++i) {
for (int j = 1; j < (int)sec.size(); ++j) {
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
if (fir[i] == sec[j])
dp[i][j] = max(dp[i][j], dp[i-1][j-1]+1);
}
}
//所以这里是size-2
cout << sec.size()-2-dp[fir.size()-1][sec.size()-1]/2 << endl;
return 0;
}