PAT 甲级 A1045(C++10ms解决)

题目连接

1045 Favorite Color Stripe (30分)

题目大意

给定一个Eva喜欢的颜色序列和一个总的颜色序列,从总的颜色序列中找出按Eva喜欢的颜色序列顺序出现的最长子序列。有点绕,结合样例来说明什么意思。假设Eva喜欢的颜色序列为 {2 3 1 5 6},总的颜色序列为{2 2 4 1 5 5 6 3 1 1 5 6}.那么需要从总的颜色序列中找出符合题意的序列有 {2 2 1 1 1 5 6}, {2 2 1 5 5 5 6}, {2 2 1 5 5 6 6}, {2 2 3 1 1 5 6}.
其中第一个序列按照2 1 5 6的顺序出现,满足。
第二,三个序列按照 2 1 5 6的顺序出现,满足。
第四个序列按照2 3 1 5 6的顺序出现,满足。

思路

用动态规划实现即可,dp[c]表示以颜色c结尾的序列长度,设dp[j]表示以颜色j结尾的序列长度,那么状态转移方程可以表示为:

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

为了保证dp[j]表示的是dp[c]更新之前的长度,这里设置了temp来表示dp[c]未更新前的最长序列长度,所以状态转移方程为:

dp[c] = max(temp[j]+1,dp[c]);

另外,Eva喜欢的颜色的出现顺序,可以用一个数组w来表示。由于总的颜色序列中不一定含有Eva所喜欢的颜色,所以在执行状态转移方程前,需要简单地判断一下。所以就很容易地写出了下面的代码。

总的来说,程序的时间复杂度为O(nm),其中m为颜色的总数(给的最大为200)。

AC代码

#include<iostream>
#define maxn 10010
#define maxc 205
using namespace std;
int n, m, l, ans = 0;
int w[maxc];
int dp[maxc],temp[maxc];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
	int c;
	cin >> n >> m;        //n没什么卵用
	for (int i = 1; i <= m; i++) {
		cin >> c;
		w[c] = i;
	}
	cin >> l;
	for (int i = 0; i < l; i++) {
		cin >> c;
		if (!w[c]) continue;
		for (int j = 0; j < maxc; j++) {
			if (!w[j] ||w[j] > w[c]) continue;
			dp[c] = max(dp[c], temp[j] + 1);
		}
		dp[c] = max(1, dp[c]);
		ans = max(dp[c], ans);
		for (int j = 0; j < maxc; j++) { //temp记录了上次的dp
			temp[j] = dp[j];
		}
	}
	cout << ans;
	return 0;
}
发布了25 篇原创文章 · 获赞 3 · 访问量 1745

猜你喜欢

转载自blog.csdn.net/qq_38507937/article/details/105518109
今日推荐