HDU-4745-Two Rabbits

HDU-4745-Two Rabbits

传送门

这一道题是区间dp.最长回文子序列。

题目大意:有两只兔子。一个只往顺时针方向跳。一个只往逆时针方向跳。这两只兔子每次跳的石头的重量必须相同。
所以很明显啦~有关于回文串的

当初思考的时候想把前面n-1个数直接放在n的后面。。然而。。出现了bug。这个求的区间dp是连续的。但是题目要求的可以不连续。。呃。。
这样思考
我们可以获得两个回文串。然后把这两个回文串组成环。
也是一个回文串。emmm这里可以举例子。
比如样例1 1 2 1
1是一个回文串
1 2 1是一个回文串
他们两个组成的环也是回文串。
所以我们可以通过这种方法求解。
那么问题又来了?这怎么知道是最长的

这个比较好解决
我们在长度为n的序列中跑一遍加起来最长的回文序列长度就行。注意不要重复。因为题目中要求不能踩踩过的石头。

所以dp[i][j]表示i~j的范围内的最长的回文串的长度。
状态转移方程:
也有两种状态。
当s[i] == s[i + len]时
s[i][i + len] = max(s[i][i + len], s[i + 1][i + len - 1] + 2);
当s[i] != s[i + len]时
s[i][i + len] = max(s[i + 1][i + len], s[i][i + len - 1]);
这个好理解。
比较i+1~i+len是否时回文串或者i ~i + len-1是否是回文串。

初始化:
dp[i][i] = 1;代表字符本身也是回文串。

代码部分:

#include <bits/stdc++.h>
#define mst(a, n) memset(a, n, sizeof(a))
using namespace std;
const int N = 1e3 + 10;

int n;
int dp[N][N];
int a[N];

int main()
{
	while (~scanf("%d", &n) && n)
	{
		for (int i = 1; i <= n; i++)
		{
			scanf ("%d", &a[i]);
		}
		mst(dp, 0);
		for (int i = 1; i <= n; i++)
		{
			dp[i][i] = 1;
		}
		for (int j = 1; j <= n; j++)
		{
			for (int i = 1; i + j <= n; i++)
			{
				dp[i][i + j] = max(dp[i + 1][i + j], dp[i][i + j - 1]);
				if (a[i] == a[i + j])
				{
					dp[i][i + j] = max(dp[i][i + j], 2 + dp[i + 1][i + j - 1]);
				}
			}
		}
		int ans = 0;
		for (int i = 1; i <= n; i++)
		{
			ans = max(ans, dp[1][i] + dp[i + 1][n]);
		}
		cout << ans << endl;
	}
	return 0;
}
发布了112 篇原创文章 · 获赞 3 · 访问量 2623

猜你喜欢

转载自blog.csdn.net/qq_44624316/article/details/105033985