zoukankan      html  css  js  c++  java
  • HDU 4745 Two Rabbits ★(最长回文子序列:区间DP)

    题意

    在一个圆环串中找一个最长的子序列,并且这个子序列是轴对称的。

    思路

    从对称轴上一点出发,向两个方向运动可以正好满足题意,并且可以证明如果抽选择的子环不是对称的话,其一定不是最长的。 倍长原序列,在新序列中求所有区间的最长回文子序列长度(一般子序列就表示不是连续的串)。 答案就等于所有长度为n的区间中最长回文的长度 和 所有长度为n-1的区间中最长回文的长度+1(在轴上的两点可不同) 中最大的那个。 【求最长回文子序列】:设dp[i][j]表示[i,j]区间内的最长回文子序列,则dp[i][j] = max(dp[i+1][j], dp[i][j-1], (if a[i]==a[j])dp[i+1][j-1]).

    代码

      [cpp] #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <string> #include <cstring> #include <vector> #include <set> #include <stack> #include <queue> #define MID(x,y) ((x+y)/2) #define MEM(a,b) memset(a,b,sizeof(a)) #define REP(i, begin, end) for (int i = begin; i <= end; i ++) using namespace std; int a[2005]; int dp[2005][2005]; int main(){ int n; while(scanf("%d", &n), n){ for (int i = 1; i <= n; i ++){ scanf("%d", &a[i]); a[i+n] = a[i]; } int n1 = n + n; MEM(dp, 0); for (int i = 1; i <= n1; i ++) dp[i][i] = 1; for (int len = 1; len < n1; len ++){ for (int i = 1; i + len <= n1; i ++){ int j = i + len; dp[i][j] = max(dp[i+1][j], max(dp[i][j-1], a[i] == a[j]?dp[i+1][j-1]+2:0)); } } int res = 0; for (int i = 1; i <= n; i ++) res = max(res, dp[i][i+n-1]); for (int i = 1; i <= n; i ++) res = max(res, dp[i][i+n-2]+1); printf("%d ", res); } return 0; } [/cpp]
  • 相关阅读:
    java+opencv实现图像灰度化
    java实现高斯平滑
    hdu 3415 单调队列
    POJ 3368 Frequent values 线段树区间合并
    UVA 11795 Mega Man's Mission 状态DP
    UVA 11552 Fewest Flops DP
    UVA 10534 Wavio Sequence DP LIS
    UVA 1424 uvalive 4256 Salesmen 简单DP
    UVA 1099 uvalive 4794 Sharing Chocolate 状态DP
    UVA 1169uvalive 3983 Robotruck 单调队列优化DP
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114123.html
Copyright © 2011-2022 走看看