描述
回文数列是一个形如{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]); } }