区间dp,关键是想模型。题目其实可以转化为求环上的最长非连续回文串,可以用区间dp做。。可以先把串copy成两个,然后再做线性的最长回文串,虽然比直接环上做时间慢一些,但是比较容易写。。dp[j][k]表示 j 到 k 表示的最长回文串,注意,这个回文串表示的只有一半,需要加的时候加 2 来保证每个人都把走完一个环。。。然后最后在考虑一下两个兔子在同一块石头的情况。。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int N = 2222;
int a[N], dp[N][N];
int main()
{
int n, i, j, ans, k;
while(scanf("%d", &n), n)
{
CLR(dp, 0);
for(i = 1; i <= n; i ++)
{
scanf("%d", &a[i]);
a[i + n] = a[i];
dp[i][i] = dp[i + n][i + n] = 1;
}
for(i = 2; i <= n; i ++)
{
for(j = 1; j + i - 1 < 2 * n; j ++)
{
k = i + j - 1;
if(a[j] == a[k]) dp[j][k] = max(dp[j][k], dp[j + 1][k - 1] + 2);
dp[j][k] = max(max(dp[j][k], dp[j + 1][k - 1]), max(dp[j + 1][k], dp[j][k - 1]));
}
}
ans = 0;
for(i = 1; i <= n; i ++) ans = max(ans, dp[i][i + n - 1]);
for(i = 1; i <= n; i ++) ans = max(ans, dp[i][i + n - 2] + 1);
printf("%d\n", ans);
}
}