题目链接:
点击打开链接
解题思路:这道题与最长上升字序列有些类似,只不过是个对称的最长上升子序列。解题思路仍是动态规划。
子问题:前j个数字和后i个数字组成的序列中的队形长度。
状态转移: 如果a[i] == a[j] 那么队列的长度等于前j-1和后i-1个数字组成的队列中中间数字小于a[i]的队列的长度加上2,
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 250;
int f[MAXN], a[MAXN];
int main()
{
int t, i, n, j, curlen, ans;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
}
ans = 1;
memset(f, 0, sizeof(f)); //注意memset的正确形式: 如果写memset(f, 0, MAXN)会出现答案错误
for(i = n; i > 0; i--)
{
curlen = 0;
for(j = 1; j <= i; j++)
{
if(a[j] < a[i]) //查找并记录比a[i]小的数形成的最长长度,
{
curlen = max(curlen, f[j]); //
}
else if(a[j] == a[i]) //如果相等,最长长度可以再加一
{
f[j] = curlen+1;
if(j < i) ans = max(ans, 2 * f[j]);
else ans = max(ans, 2 * f[j] - 1); //考虑长度为奇数的情况,要减1
}
}
}
printf("%d\n", ans);
}
return 0;
}