http://acm.hdu.edu.cn/showproblem.php?pid=4512
题意:中文题,给你一个 队列,要你在不改变队列顺序的情况下选几个人出来组成一个对称的先上升后下降的队列,问最多选多少人。
思路:将队列倒过来和原队列求最长上升公共子序列,dp[i][k] 表示序列a中[1, i]和b序列中[1, k]选出的最长的以b[k]结尾的上升公共子序列。
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n;
int arg[210];
int dp[210][210];
int main()
{
int Test;
cin>>Test;
while(Test--){
cin>>n;
for(int i = 1; i <= n; i++){
cin>>arg[i];
}
int maxn = 1;
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= n; i++)
{
int ans = 0;
for(int k = n; k > i; k--)
{
dp[i][k] = dp[i-1][k]; //a[i] != b[i]
if(arg[i] > arg[k] && ans < dp[i-1][k]) //当前循环求得是以a[i]结尾的公共子序列
ans = dp[i-1][k]; //保存结尾比a[i]小的最长子序列
if(arg[i] == arg[k]){ //转移
dp[i][k] = ans + 1;
}
if((dp[i][k]<<1) > maxn){
maxn = dp[i][k]<<1; //对称所以乘二
}
for(int l = i+1; l < k; l++) //中间有没有比a[i]大
{
if(arg[l] > arg[k] && (dp[i][k] << 1 | 1) > maxn){
maxn = (dp[i][k]<< 1 | 1); //乘 2 加 1
}
}
}
}
cout<<maxn<<endl;
}
return 0;
}