hdu 4745 Two Rabbits 环形最长回文子序列
Two Rabbits
---------------------------------------------------------------------模型可以转化为求长度为n的序列的最长回文子序列
方法为枚举起点+记忆化+环形dp
用next(i)代替i++,prev(i)代替i--
f[i][j]表示环(i,j)的最长回文子序列。
若i=j则环区间为空,
若i>j则区间为 i i+1 i+2 ... n-1 ... j-2 j-1 j
若i<j则区间为 i i+1 ... j-1 j
枚举起点i, 分为以i为起点向两端寻找与不以i为起点但是环区间在 (i+1,i) 两端两种情况。
---------------------------------------------------------------------
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> using namespace std; const int maxn=1111; int a[maxn]; int f[maxn][maxn]; int n; int prev(int x){ return (x-1+n)%n; } int next(int x){ return (x+1)%n; } int dp(int l,int r){ if (l==r) return 1; if (next(l)==r) return 1+(a[l]==a[r]); if (f[l][r]!=-1) return f[l][r]; if (a[l]==a[r]) return f[l][r]=dp(next(l),prev(r))+2; return f[l][r]=max(dp(next(l),r),dp(l,prev(r))); } int main() { int ans; while (~scanf("%d",&n)){ if (n==0) break; ans=0; memset(f,-1,sizeof(f)); for (int i=0;i<n;i++){ scanf("%d",&a[i]); } if (n==1) ans=1; else if (n==2) ans=2; else{ for (int i=0;i<n;i++){ ans=max(ans,dp(next(i),prev(i))+1); //ans=max(ans,dp(i,prev(i))); ans=max(ans,dp(next(i),i)); } } printf("%d\n",ans); } return 0; }