[PAT_A 1045]Favorite Color Stripe

在这里插入图片描述

题目大意:
给出m种颜色作为主人公Eva喜欢的颜色,同时也给出顺序,然后给出一串长度为L的颜色序列,现在要去掉这个序列中Eva不喜欢的颜色,然后求剩余的一个子序列,使得这个子序列表示的颜色顺序符合Eva喜欢的颜色的顺序(不一定所有喜欢的颜色都要出现),且为所有满足这个条件的子序列中长度最长的子序列,输出其长度。

样例解释:
喜欢的序列:2 3 1 5 6
给出长度为12的序列 2 2 4 1 5 5 6 3 1 1 5 6
去掉Eva不喜欢的颜色后的序列 2 2 1 5 5 6 3 1 1 5 6
最长子序列 2 2 3 1 1 5 6 长度为7

思路一:最长不下降子序列(LIS)
由于题目给出了Eva喜欢的颜色顺序,而已知最长不下降子序列问题中寻找的子序列是一个非递减的序列,因此可以将Eva喜欢的颜色映射的到一个递增序列,如本题的,Eva喜欢的5中颜色分别为{2,3,1,5,6},则将它们映射成为{0,1,2,3,4},而其他不在这5中颜色中都可以映射称-1,然后就可以将寻找给定顺序的颜色的问题转换成为一个求解最长不下降子序列的问题。

AC代码:

//PAT_A 1045
//LIS实现
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 210;
const int maxc = 10010;
int hashTable[maxn];
int A[maxc], dp[maxc];
int main() {
	int n, m, x;
	(void)scanf("%d %d", &n, &m);
	fill(hashTable, hashTable + maxn, -1);
	for (int i = 1; i <= m; i++) {
		(void)scanf("%d", &x);
		hashTable[x] = i;//喜爱的颜色映射成为0~n-1
	}
	int L, num = 0;
	(void)scanf("%d", &L);
	for (int i = 0; i < L; i++) {
		(void)scanf("%d", &x);
		if (hashTable[x] > 0) {//剔除掉不喜欢颜色的序列
			A[num++] = hashTable[x];//A中存储映射之后的键值
		}
	}
	int ans = 0;
	for (int i = 0; i < num; i++) {
		dp[i] = 1;
		for (int j = 0; j < i; j++) {
			if (A[i] >= A[j])dp[i] = max(dp[i], dp[j] + 1);
		}
		if (dp[i] > ans)ans = dp[i];
	}
	printf("%d\n", ans);
	return 0;
}

思路二:最长公共子序列(LCS)
令dp[i][j]表示A的i号位与B的j号位之前的LCS长度。
由于经典的LCS模型的两个序列的元素匹配必须是一一对应的,但本题中允许公共部分产生重复元素。
如ABBC与AABC的最长公共子序列是AABBC。

在原模型的基础上改进:
由于可以产生重复元素,当A[i]与B[j]相等时,dp[i][j]应该等于dp[i-1][j]与dp[i][j-1]中的较大值+1,
(若不计算重复元素则dp[i][j]=dp[i-1][j-1]+1)
当A[i]与B[j]不相等的时候,dp[i][j]继承dp[i-1][j]与dp[i][j-1]中的较大值。

则状态转移方程:
1)if(A[i]==B[j]) dp[i][j]=max{dp[i-1][j],dp[i][j-1]}+1
2)if(A[i]!=B[j]) dp[i][j]=max{dp[i-1][j],dp[i][j-1]}

这种方式不用去除掉输入序列中的不喜欢的元素,因为这些元素不会进入到公共子序列中。

AC代码:

//PAT_A 1045
//LCS实现
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxc = 210;
const int maxn = 10010;
int a[maxc], b[maxn], dp[maxc][maxn];
int main() {
	int n, m, l;
	(void)scanf("%d %d", &n, &m);
	for (int i = 1; i <= m; i++) {
		(void)scanf("%d", &a[i]);
	}
	(void)scanf("%d", &l);
	for (int j = 1; j <= l; j++) {
		(void)scanf("%d", &b[j]);
	}
	for (int i = 0; i <= m; i++) {
		dp[i][0] = 0;
	}
	for (int i = 0; i <= l; i++) {
		dp[0][i] = 0;
	}
	for (int i = 1; i <= m; i++) {
		for (int j = 1; j <= l; j++) {
			if (a[i] == b[j])dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + 1;
			else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
		}
	}
	printf("%d\n", dp[m][l]);
	return 0;
}
发布了142 篇原创文章 · 获赞 1 · 访问量 4559

猜你喜欢

转载自blog.csdn.net/weixin_44699689/article/details/104677133
今日推荐