题意:把一段相同的形状变成其它任意一个形状,需要使用一次魔法,问最少使用多少魔法能使全是同一个形状。
思路:
先把连续的缩成一个连续段,假设缩点后有m个段,如果每个
互不相同,答案显然是m-1,不管怎样合都对答案没有影响。如果在合并两个区间时,两个区间的左、右端点的值相同,那么可以通过将中间的值赋值成该值,可以省去一步。
假设表示合并区间
的最小代价,
表示与
相同的点的下标。枚举
有没有参与省去的过程,即
。同时注意考虑一下左端点相同的情况:
MyCode:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+7,maxm=2e5+7;
typedef long long int ll;
typedef unsigned long long ull;
int a[5001],f[5001][5001],u[5001],lt[5001];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T,n;
cin>>T;
while(T--) {
cin>>n;
for(int i=1;i<=n;++i) {
cin>>a[i];
if(a[i]==a[i-1]) --i,--n;
u[a[i]]=0;
}
for(int i=1;i<=n;++i) {
lt[i]=u[a[i]];
u[a[i]]=i;
f[i][i]=0;
}
for(int len=2;len<=n;++len)
for(int l=1,r=l+len-1;l<=n-len+1;++l,++r) {
f[l][r]=f[l][r-1]+1;
for(int k=lt[r];k>=l;k=lt[k])
f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]);
}
cout<<f[1][n]<<'\n';
}
return 0;;
} 
京公网安备 11010502036488号