4541 回文数列

描述

 回文数列是一个形如{a1,a2,a3,...,a3,a2,a1}的整数序列。现给定任意一个整数数列

{a1,a2,a3,...,an},请插入个数最少的整数,使其成为一个回文数列。

 输入

 输入数据有多组,第一行为整数T(t<=30),表示数据组数。每组数据占2行,第1行为整数n(1<=n<=10000),第2行有n个正整数a1,a2,...,an,每个整数不大于100。

 输出

 每组数据输出一个整数m,表示最少插入m次即可以将数列变成回文数列。数据保证m<100。

 样例输入

2
2
1 2
3
1 2 1

样例输出

1
0

思路: 求出最长回文子序列的长度,原序列长度-最长回文子序列长度即最少的插入个数。

dp求最长回文子序列长度:dp[i][j]表示第i个字符到第j个字符的最长回文子序列长度

状态方程  dp[i][j]=dp[i + 1][j - 1] + 2    (当第i个字符和第j个字符匹配)

                 dp[i][j]=max(dp[i][j - 1], dp[i+1][j])    (当第i个字符和第j个字符不匹配)

 

#include<bits/stdc++.h>
using namespace std;
int t;
int a[10005],f[105],dp[2][10005];
int main(){
     scanf("%d",&t);
     while(t--){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        memset(dp,0,sizeof(dp));
        for(int i=n;i>=1;i--){
            memcpy(dp[1],dp[0],sizeof(dp[1]));
            dp[0][i]=1;
            for(int j=i+1;j<=n;j++){
                if(a[i]==a[j])
                    dp[0][j]=dp[1][j-1]+2;
                else
                    dp[0][j]=max(dp[1][j],dp[0][j-1]);
            }
        }
        printf("%d\n",n-dp[0][n]);
     }
}
View Code

 

                

 

猜你喜欢

转载自www.cnblogs.com/llhsbg/p/12803172.html