HDU 4745 Two Rabbits(非连续最长回文子序列,区间DP)

2023-11-10 00:32

本文主要是介绍HDU 4745 Two Rabbits(非连续最长回文子序列,区间DP),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Two Rabbits(最长回文子串的长度)

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 2398    Accepted Submission(s): 1244

 

Problem Description

Long long ago, there lived two rabbits Tom and Jerry in the forest. On a sunny afternoon, they planned to play a game with some stones. There were n stones on the ground and they were arranged as a clockwise ring. That is to say, the first stone was adjacent to the second stone and the n-th stone, and the second stone is adjacent to the first stone and the third stone, and so on. The weight of the i-th stone is ai.

The rabbits jumped from one stone to another. Tom always jumped clockwise, and Jerry always jumped anticlockwise.

At the beginning, the rabbits both choose a stone and stand on it. Then at each turn, Tom should choose a stone which have not been stepped by itself and then jumped to it, and Jerry should do the same thing as Tom, but the jumping direction is anti-clockwise.

For some unknown reason, at any time , the weight of the two stones on which the two rabbits stood should be equal. Besides, any rabbit couldn't jump over a stone which have been stepped by itself. In other words, if the Tom had stood on the second stone, it cannot jump from the first stone to the third stone or from the n-the stone to the 4-th stone.

Please note that during the whole process, it was OK for the two rabbits to stand on a same stone at the same time.

Now they want to find out the maximum turns they can play if they follow the optimal strategy.

 

 

Input

The input contains at most 20 test cases.
For each test cases, the first line contains a integer n denoting the number of stones.
The next line contains n integers separated by space, and the i-th integer ai denotes the weight of the i-th stone.(1 <= n <= 1000, 1 <= ai <= 1000)
The input ends with n = 0.

 

 

Output

For each test case, print a integer denoting the maximum turns.

 

 

Sample Input

1

1

4

1 1 2 1

6

2 1 1 2 1 3

0

 

 

Sample Output

1

4

5

Hint

 

For 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.

 

 

 

Source

2013 ACM/ICPC Asia Regional Hangzhou Online

 

 

Recommend

liuyiding   |   We have carefully selected several similar problems for you:  6408 6407 6406 6405 6404 

题意:

给定一个环状数列,求一个最长的回文子序列

分析:

环状数列很好解决,直接把数组扩开一倍即可。

我们定义f[l][r]表示l到r区间的最长非连续的的回文子序列总体长度

如果s[l]==s[r] 则 f[l][r]=f[l+1][r-1]+2;

不然 f[l][r]=max(f[l+1][r],f[l][r-1]);

要点

阶段:区间长度

状态:开始端点

决策:两种情况

状态转移方程:

s[l]==s[r] 则 f[l][r]=f[l+1][r-1]+2;

不然 f[l][r]=max(f[l+1][r],f[l][r-1]);

初始条件:f[i][i]=1,其余为0

目的:长度为n的所有dp[i][j]

但上述仅仅是求出一个序列的非连续最长回文子序列,题目的序列是环状的,先上正确答案代码

for (int i = 1; i <= n; i++){//cout<<dp[1][i]<<" "<<dp[i+1][n]<<endl;ans = max(ans, dp[1][i] + dp[i + 1][n]);}

我们想一下因为他是一个环,1~i之间分两份,i~n之间分两分

则b+c和a+d构成一个更大的回文串

代码实现:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<map>
#include<vector>using namespace std;inline int read()
{int x=0,f=1;char ch=getchar();while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;
}const int maxn = 3010;int a[maxn],f[maxn][maxn];
int n,m;
int ans;int main()
{ while (1){scanf("%d",&n);memset(f,0,sizeof(f));memset(a,0,sizeof(a));if (n==0) return 0;ans=0;      for (int i=1;i<=n;i++)scanf("%d",&a[i]),a[i+n]=a[i];for (int i=1;i<=2*n;i++)f[i][i]=1;for (int i=2;i<=2*n;i++){for (int l=1;l<=2*n-i+1;l++){int r=l+i-1;if (a[l]==a[r]) f[l][r]=max(f[l][r],f[l+1][r-1]+2);else f[l][r]=max(f[l][r-1],f[l+1][r]);}}for (int i=1;i<=n;i++){ans=max(ans,f[1][i]+f[i+1][n]);}printf("%d\n",ans);}return 0;
}

这篇关于HDU 4745 Two Rabbits(非连续最长回文子序列,区间DP)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/379380

相关文章

C++从序列容器中删除元素的四种方法

《C++从序列容器中删除元素的四种方法》删除元素的方法在序列容器和关联容器之间是非常不同的,在序列容器中,vector和string是最常用的,但这里也会介绍deque和list以供全面了解,尽管在一... 目录一、简介二、移除给定位置的元素三、移除与某个值相等的元素3.1、序列容器vector、deque

C++实现回文串判断的两种高效方法

《C++实现回文串判断的两种高效方法》文章介绍了两种判断回文串的方法:解法一通过创建新字符串来处理,解法二在原字符串上直接筛选判断,两种方法都使用了双指针法,文中通过代码示例讲解的非常详细,需要的朋友... 目录一、问题描述示例二、解法一:将字母数字连接到新的 string思路代码实现代码解释复杂度分析三、

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

关于最长递增子序列问题概述

《关于最长递增子序列问题概述》本文详细介绍了最长递增子序列问题的定义及两种优化解法:贪心+二分查找和动态规划+状态压缩,贪心+二分查找时间复杂度为O(nlogn),通过维护一个有序的“尾巴”数组来高效... 一、最长递增子序列问题概述1. 问题定义给定一个整数序列,例如 nums = [10, 9, 2

hdu4826(三维DP)

这是一个百度之星的资格赛第四题 题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1004&cid=500 题意:从左上角的点到右上角的点,每个点只能走一遍,走的方向有三个:向上,向下,向右,求最大值。 咋一看像搜索题,先暴搜,TLE,然后剪枝,还是TLE.然后我就改方法,用DP来做,这题和普通dp相比,多个个向上

hdu1011(背包树形DP)

没有完全理解这题, m个人,攻打一个map,map的入口是1,在攻打某个结点之前要先攻打其他一个结点 dp[i][j]表示m个人攻打以第i个结点为根节点的子树得到的最优解 状态转移dp[i][ j ] = max(dp[i][j], dp[i][k]+dp[t][j-k]),其中t是i结点的子节点 代码如下: #include<iostream>#include<algorithm

hdu4865(概率DP)

题意:已知前一天和今天的天气概率,某天的天气概率和叶子的潮湿程度的概率,n天叶子的湿度,求n天最有可能的天气情况。 思路:概率DP,dp[i][j]表示第i天天气为j的概率,状态转移如下:dp[i][j] = max(dp[i][j, dp[i-1][k]*table2[k][j]*table1[j][col] )  代码如下: #include <stdio.h>#include

poj2406(连续重复子串)

题意:判断串s是不是str^n,求str的最大长度。 解题思路:kmp可解,后缀数组的倍增算法超时。next[i]表示在第i位匹配失败后,自动跳转到next[i],所以1到next[n]这个串 等于 n-next[n]+1到n这个串。 代码如下; #include<iostream>#include<algorithm>#include<stdio.h>#include<math.

poj3261(可重复k次的最长子串)

题意:可重复k次的最长子串 解题思路:求所有区间[x,x+k-1]中的最小值的最大值。求sa时间复杂度Nlog(N),求最值时间复杂度N*N,但实际复杂度很低。题目数据也比较水,不然估计过不了。 代码入下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring

csu1328(近似回文串)

题意:求近似回文串的最大长度,串长度为1000。 解题思路:以某点为中心,向左右两边扩展,注意奇偶分开讨论,暴力解即可。时间复杂度O(n^2); 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring>#include<string>#inclu