hdu6570 动态规划 dp

题目链接:hdu6570
题目大意(机翻):
Avin正在研究系列。 如果满足以下条件,则一个系列称为“波动”:
1)它至少包含两个元素;
2)所有位于奇数位置的元素都相同;
3)偶数位置的所有元素都相同;
4)奇数位置的元素与偶数位置的元素不同。
您得到的序列长度为n。 Avin要求您找到最长的“波浪”子系列。 子系列是系列的子序列。

第一眼看见,我就觉得他是个dp(看题解才知道暴力也行);
我是这么考虑的在一开始
f[i][j][0/1]: 表示的是选取了第i个数字后是奇数长度还是偶数长度, 然后如果当前长度是奇数,则j代表偶数位置的数的大小是j,如果当前长度是偶数则同理。(0代表链长为偶数,1是奇数)考虑如何转移,我们知道了j之后只要去枚举1-(i-1)位置的所有数字,然后当那个位置的数是j就去选取f[k][value[i]][(0/1)^1]
就是原本是奇数你这时候就要选取偶数,原本是偶数也同理。
但是这样就是n^2,会超时,就考虑去优化。我是选择使用的
g[i][j][(0/1)]去代表着前k个数那个某个位置的数为i然后选择了i之后的长度是偶数还是奇数,与他对应的数字是j的最大长度
就从原本枚举f的1-(i-1)变成了直接拿g[j][value[i]][(0/1)^1];

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define ll long long
const int inf = 1e9 + 7;
const int max_ = 1e5 + 500;
int mod = 100003;
inline int read()
{
	int s = 0, f = 1;
	char ch = getchar();
	while (ch<'0' || ch>'9') {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch >= '0'&&ch <= '9') {
		s = s * 10 + ch - '0';
		ch = getchar();
	}
	return s * f;
}
int f[max_][100][3], g[100+50][100 + 50][3],n,c,node[max_];
int max(int a, int b) {
	return a > b ? a : b;
}
int main() {
	n = read(), c = read();
	for (int i = 1; i <= n; i++) {
		node[i] = read();
	}
	int ans = -1;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= c; j++) {
			if (j == node[i])continue;
			//选了i后是偶,奇位置上的是j
			f[i][j][0] = g[j][node[i]][1] + 1;
			//选了i后是奇,偶位置上的是j
			f[i][j][1] = g[j][node[i]][0] + 1;
			g[node[i]][j][0] = max(g[node[i]][j][0], f[i][j][0]);
			g[node[i]][j][1] = max(g[node[i]][j][1], f[i][j][1]);
			ans = max(ans, max(f[i][j][0], f[i][j][1]));
		}
	}
	if (ans == 1) {
		cout << "0"<<endl;
		return 0;
	}
	cout << ans << endl;
	return 0;
}

发布了32 篇原创文章 · 获赞 3 · 访问量 659

猜你喜欢

转载自blog.csdn.net/qq_43804974/article/details/103222182