题意:
两只兔子,在n块围成一个环形的石头上跳跃,每块石头有一个权值ai,一只从左往右跳,一只从右往左跳,每跳一次,两只兔子所在的石头的权值都要相等,在一圈内(各自不能超过各自的起点,也不能再次回到起点)它们最多能经过多少个石头(1 <= n <= 1000, 1 <= ai <= 1000)。
分析:
其实就是求一个环中,非连续最长回文子序列的长度。
dp[i][j] = max{ dp[i + 1][j], d[i][j - 1], (if a[i] == a[j]) dp[i + 1][j - 1] + 2 }
直接当成一个链求dp,然后把链切成两半,求出两边的回文长度,最大的和就是解。这里不用考虑起点问题,因为两边的回文中点都可以做起点。
1 1 4 1 1 2 1 6 2 1 1 2 1 3 0
1 4 5HintFor the second case, the path of the Tom is 1, 2, 3, 4, and the path of Jerry is 1, 4, 3, 2. For the third case, the path of Tom is 1,2,3,4,5 and the path of Jerry is 4,3,2,1,5.
#include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; #define ll long long #define prt(k) cerr<<#k" = "<<k<<endl const int N = 2014; int dp[N][N]; int a[N]; int main() { int n; while(cin>>n,n) { for(int i=1;i<=n;i++) scanf("%d", a+i); memset(dp,0,sizeof dp); for(int i=1;i<=n;i++) dp[i][i] = 1; for(int len=2;len<=n;len++) { for(int i=1;i+len-1<=n;i++) { int j=i+len-1; dp[i][j]=max(dp[i][j-1], dp[i+1][j]); if(a[i]==a[j]) dp[i][j]=max(dp[i][j], dp[i+1][j-1] + 2); } } int ans=0; for(int i=1;i<=n;i++)ans=max(ans,dp[1][i]+dp[i+1][n]); printf("%d\n",ans); } }
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <vector> using namespace std; #define prt(k) cout<<#k"="<<k<<endl; const int inf = 0x3f3f3f3f; struct P { int x,y; P() {} P(int xx, int yy) { x=xx, y=yy; } }p[33]; int n; struct Mat { P p[4]; int maxx, minx, maxy, miny; int S; Mat() {} Mat(P a, P b, P c, P d) { p[0] = a; p[1] = b; p[2] = c; p[3] = d; maxx = maxy = -inf; minx = miny = inf; for(int i=0;i<4;i++) { maxx = max(maxx, p[i].x); maxy = max(maxy, p[i].y); minx = min(minx, p[i].x); miny = min(miny, p[i].y); } S = (maxy - miny) * (maxx - minx); } bool in(P a) { return minx<=a.x&&a.x<=maxx && miny<=a.y&&a.y<=maxy; } bool inside(P a) { return minx<a.x&&a.x<maxx && miny<a.y&&a.y<maxy; } }; vector<Mat> mat; int jiao(Mat a, Mat b) { int c1=0; int c2=0; int t1 = 0; int t2 = 0; for(int i=0;i<4;i++) { if(b.inside(a.p[i])) c1++; if(a.inside(b.p[i])) c2++; if(b.in(a.p[i])) t1++; if(a.in(b.p[i])) t2++; } int t ; if((c1==4) || (c2==4)) t = max(a.S, b.S); else { if(t1==0 && t2==0) { t = a.S + b.S; } else t = -1; } return t; } int main() { while(cin>>n, n) { for(int i=0;i<n;i++) cin>>p[i].x>>p[i].y; mat.clear(); for(int a=0;a<n;a++) for(int b=a+1;b<n;b++) if(p[a].x == p[b].x) for(int c=0;c<n;c++) if(p[a].y == p[c].y && a != c && b != c) for(int d=0; d<n; d++) if(p[d].y == p[b].y && p[d].x == p[c].x) { Mat t = Mat(p[a],p[b],p[c],p[d]); if(t.S==0) continue; mat.push_back(t); } int m = mat.size(); int ans = -1; for(int i=0;i<m;i++) for(int j=i+1;j<m;j++) { int tmp = jiao(mat[i], mat[j]); ans = max(ans, tmp); } if(ans == -1) puts("imp"); else printf("%d\n", ans); } return 0; }