题目
思路
题目大意:给一些喜欢的颜色,注意这些颜色是有优先级的;再给一个颜色数组,从这个颜色数组中找到最长的子序列,要求这个子序列中的颜色都是喜欢的颜色,且顺序与给的颜色优先级顺序一致(但不要求每个喜欢的颜色都被选择);
这道题的巧妙之处在于转化为了一个求最长不下降子序列长度问题,因为喜欢的颜色是有优先级的,所以可以从0到n标号,代表优先级;然后把给的颜色序列中不喜欢额颜色剔除,只剩下喜欢的,且喜欢的颜色用其优先级表示;这样就转化为了求最长不下降子序列长度问题;
状态划分和转移:dp[i] 代表以第i个元素结尾的最长子序列长度,要想求出来dp[i],需要从dp[0]-dp[i - 1]转化过来;初始dp[i] = 1,依次遍历dp[j] (j <= 0 < i ),如果dp[j] + 1 > 1,则需要更新状态dp[i];
代码
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cstring>
#include <string>
#include <math.h>
#include <set>
#include <map>
using namespace std;
const int maxn = 1e4 + 10;
const int maxc = 210;//最大的颜色数
int A[maxn], hashColor[maxc], dp[maxn];
int main()
{
int n, m, num = 0, c;//num记录有效元素个数
scanf("%d%d", &n, &m);
fill(hashColor, hashColor + maxn, -1);//不喜爱的颜色标为-1
//依次为喜爱的颜色从0到n编号,转化为最长不下降子序列问题
for(int i = 0; i < m; i ++){
scanf("%d", &c);
hashColor[c] = i;
}
scanf("%d", &n);
for(int i = 0; i < n; i ++){
scanf("%d", &c);
//如果是喜爱的颜色,加入有效数组A
if(hashColor[c] != -1){
A[num ++] = hashColor[c];
}
}
int ans = 0;
//状态转移
for(int i = 0; i < num; i ++){
dp[i] = 1;//状态初始化
for(int j = 0; j < i; j ++){
//如果第j个数小于第i个数,并且状态dp[j] + 1 > dp[i]
if(A[j] <= A[i] && dp[j] + 1 > dp[i]){
dp[i] = dp[j] + 1;
}
}
ans = max(dp[i], ans);
}
printf("%d\n", ans);
system("pause");
return 0;
}