DP果真是考思维啊
增加一个数的操作等价于删掉那个不和谐的数的操作。
所以1、2操作可以忽略。
剩下3、4操作,则可以设计f[i][j]是将区间[i,j]变成回文序列需要的操作数。
if(a[i]==a[j]) f[i][j]=f[i+1][j-1];
如果不一致的话,考虑改、删左边、删右边三种操作。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #include<algorithm> using std::min; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } int f[3300][3300]; int s[3300]; int main(){ int n=read(); for(int i=1;i<=n;++i) s[i]=read(); for(int len=2;len<=n;++len) for(int i=1;i+len-1<=n;++i){ int j=i+len-1; f[i][j]=0x7fffffff; if(s[i]==s[j]) f[i][j]=f[i+1][j-1]; else{ f[i][j]=min(f[i][j],f[i+1][j-1]+1); f[i][j]=min(f[i][j],f[i][j-1]+1); f[i][j]=min(f[i][j],f[i+1][j]+1); } } printf("%d",f[1][n]); return 0; }