HDU4745 Two Rabbits

把模型抽象出来,其实就是在一个环中找一个最长的子环,并且这个子环是轴对称的。

从对称轴上一点出发,向两个方向运动可以正好满足题意,并且可以证明如果抽选择的子环不是对称的话,其一定不是最长的。

倍长原序列,在新序列中求所有区间的最长回文子序列长度。

答案就等于所有长度为n的区间中最长回文的长度 和 所有长度为n-1的区间中最长回文的长度+1(在轴上的两点可不同) 中最大的那个。


#pragma comment(linker,"/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <vector>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;
typedef long long ll;

const int maxn = 2010;
int n, n2, ans;
int a[maxn];
int dp[maxn][maxn];

int main()
{
    while (scanf("%d", &n) == 1 && n)
    {
        for (int i=1;i<=n;i++) scanf("%d", &a[i]);
        for (int i=1;i<=n;i++) a[i+n] = a[i];
        memset(dp, 0, sizeof(dp));
        n2 = n+n;
        for (int i=1;i<=n2;i++) dp[i][i] = 1;
        for (int l=2;l<=n;l++)
            for (int i=1;i+l-1<=n2;i++)
            {
                int j = i+l-1;
                dp[i][j] = max(max(dp[i][j], dp[i+1][j-1] + (a[i] == a[j] ? 2 : 0)), max(dp[i+1][j], dp[i][j-1]));
            }
        ans = 0;
        for (int i=1;i<=n;i++) ans = max(ans, dp[i][i+n-1]);
        for (int i=1;i<=n;i++) ans = max(ans, dp[i][i+n-2]+1);
        printf("%d\n", ans);
    }
    return 0;
}



你可能感兴趣的:(HDU4745 Two Rabbits)