写倒是很好写,但是重要的是读懂题并且抽象出模型。两只兔子一个顺时针跳,一个逆时针跳,每次只能跳到数值相同的石头上,且不能跨过之前跳过的时候,本质其实是求一个环的最长回文子序列。
dp[i][j]表示(i,j)这个区间的最长回文子序列长度,转移方程dp[i][j]=max(dp[i+1][j], dp[i][j-1], dp[i+1][j-1]+(a[i]==a[j]?2:0))
然后处理环可以将序列倍长,或者枚举中点,算两边的子序列就行。
1 #include <stdio.h> 2 const int maxn = 1005; 3 int T, n, a[maxn], dp[maxn][maxn]; 4 inline int max(int x, int y) { return x > y ? x : y; } 5 int main() { 6 while (~scanf("%d", &n) && n) { 7 for (int i = 1; i <= n; ++i) { 8 scanf("%d", &a[i]); 9 dp[i][i] = 1; 10 if (i == 1) 11 continue; 12 if (a[i] == a[i - 1]) 13 dp[i - 1][i] = 2; 14 else 15 dp[i - 1][i] = 1; 16 } 17 for (int d = 2; d < n; ++d) 18 for (int i = 1; i + d <= n; ++i) { 19 dp[i][i + d] = max(dp[i + 1][i + d], dp[i][i + d -1]); 20 dp[i][i + d] = max(dp[i][i + d], dp[i + 1][i + d -1] + (a[i] == a[i + d] ? 2 : 0)); 21 } 22 int ans = 1; 23 for (int i = 1; i < n; ++i) 24 ans = max(ans, dp[1][i] + dp[i + 1][n]); 25 printf("%d\n", ans); 26 } 27 return 0; 28 }