一开始我的思路就是dfs+剪枝,用一个vector来记录对应数字的所有下标,接着枚举
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
const int N = (int)5e5 + 5;
int a[N]; int n;
vector<int> b[N];
int ans = N;
void dfs(int now, int step) {
if (now == n + 1) {
ans = min(ans, step);
return;
}
int t = a[now];
if (b[t].size() < 2) return;
for (auto u : b[t]) {
//if (b[a[u + 1]].size() < 2) continue; // 提前减枝会出现问题
if (u > now)
dfs(u + 1, step + 1);
}
}
int main() {
cin >> n;
if (n == 1) {
cout << -1;
return 0;
}
for (int i = 1; i <= n; i++) {
cin >> a[i];
b[a[i]].push_back(i);
}
if (a[1] == a[n]) {
cout << 1; return 0;
}
if (b[a[1]].size() == 1 || b[a[n]].size() == 1) {
cout << -1; return 0;
}
dfs(1, 0);
if(ans!=N)
cout << ans;
else cout << -1;
return 0;
}
可惜的是只过了百分之八十的测试集
那怎么办,我们只能用dp来优化,用dp[i] 表示以i结尾的最小代价,用mn[ a[i] ] 记录上一个a[i] 之前的最小代价,我们的转移方程就是dp[i] = mn[a[i]] + 1 ,并且更新一下mn[a[i]]
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
const int N = (int)5e5 + 5;
int a[N]; int n;
int dp[N];
int mn[N];
int main() {
cin >> n;
if (n == 1) {
cout << -1;
return 0;
}
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
memset(mn,0x3f,sizeof mn);
for(int i=1;i<=n;i++){
dp[i] = mn[a[i]] + 1;
mn[a[i]] = min(dp[i-1],mn[a[i]]);
}
if(dp[n]>=1e6) cout << -1;
else cout << dp[n];
return 0;
}