您的位置:首页 > 其它

[HDU 4512] 吉哥系列故事——完美队形I 最长上升公共子序列

2015-08-05 08:33 330 查看
http://acm.hdu.edu.cn/showproblem.php?pid=4512

题意:中文题,给你一个 队列,要你在不改变队列顺序的情况下选几个人出来组成一个对称的先上升后下降的队列,问最多选多少人。

思路:将队列倒过来和原队列求最长上升公共子序列,dp[i][k] 表示序列a中[1, i]和b序列中[1, k]选出的最长的以b[k]结尾的上升公共子序列。



[code]#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: