hdu 4745 Two Rabbits 区间DP

http://acm.hdu.edu.cn/showproblem.php?pid=4745

题意:

有两只兔子Tom Jerry, 他们在一个用石头围城的环形的路上跳, Tom只能顺时针跳,Jerry只能逆时针跳,  要求在跳的过程中他们所在石头的权值必须相同,而且只能单向跳,中间不能有已经跳过的石头。

思路:

模型就是求环上的最长回文串,我们只要将原串倍增,然后每个长度为n的子串的最长回文串就是我们要求的。区间DP一下就好了, 注意要考虑起点终点是统一点的情况特殊。

//#pragma comment(linker, "/STACK:1024000000,1024000000")

#include <iostream>

#include <cstdio>

#include <cmath>

#include <vector>

#include <cstring>

#include <algorithm>

#include <string>

#include <set>

#include <functional>

#include <numeric>

#include <sstream>

#include <stack>

#include <map>

#include <queue>



#define CL(arr, val)    memset(arr, val, sizeof(arr))



#define lc l,m,rt<<1

#define rc m + 1,r,rt<<1|1

#define pi acos(-1.0)

#define ll long long

#define L(x)    (x) << 1

#define R(x)    (x) << 1 | 1

#define MID(l, r)   (l + r) >> 1

#define Min(x, y)   (x) < (y) ? (x) : (y)

#define Max(x, y)   (x) < (y) ? (y) : (x)

#define E(x)        (1 << (x))

#define iabs(x)     (x) < 0 ? -(x) : (x)

#define OUT(x)  printf("%I64d\n", x)

#define keyTree (chd[chd[root][1]][0])

#define Read()  freopen("din.txt", "r", stdin)

#define Write() freopen("dout.txt", "w", stdout);





#define M 107

#define N 1007



using namespace std;



int dx[4]={-1,1,0,0};

int dy[4]={0,0,-1,1};



const int inf = 0x7f7f7f7f;

const int mod = 1000000007;

const double eps = 1e-8;

const int R = 100007;



int dp[2*N][2*N];

int a[2*N];

int n;



int main()

{

    while (~scanf("%d",&n))

    {

        if (!n) break;

        CL(dp,0);

        for (int i = 1; i <= n; ++i)

        {

            scanf("%d",&a[i]);

            a[i + n] = a[i];

            dp[i][i] = dp[i + n][i + n] = 1;

        }

        //没句串的长度

        for (int i = 2; i <= n; ++i)

        {

            for (int j = 1; j + i - 1 <= 2*n; ++j)

            {

                int k = j + i - 1;

                if (a[j] == a[k]) dp[j][k] = dp[j + 1][k - 1] + 2;

                else

                {

                    dp[j][k] = max(dp[j][k], max(dp[j + 1][k], dp[j][k - 1]));

                }

            }

        }

        int ans = 0;

        for (int i = 1; i <= n; ++i) ans = max(ans, dp[i][i + n - 1]);

        //起点终点是同一点的情况

        for (int i = 1; i <= n; ++i) ans = max(ans, dp[i][i + n - 2] + 1);

        printf("%d\n",ans);

    }

    return 0;

}

  

你可能感兴趣的:(HDU)