HDU 4745 Two Rabbits 区间dp 环状最长回文子序列

题目简介

写倒是很好写,但是重要的是读懂题并且抽象出模型。两只兔子一个顺时针跳,一个逆时针跳,每次只能跳到数值相同的石头上,且不能跨过之前跳过的时候,本质其实是求一个环的最长回文子序列。

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 }
View Code

 

posted @ 2016-11-14 20:02  Apiec  阅读(280)  评论(0编辑  收藏  举报