PAT-A-1045 Favorite Color Stripe (30 分) 动态规划--最长非降子序列 C++题解
1045 Favorite Color Stripe (30 分)
题目传送门:1045 Favorite Color Stripe (30 分)
一、题目大意
给定数组1、数组2,求数组2的最长的符合数组1中元素顺序的子序列。
For example, given a stripe of colors {2 2 4 1 5 5 6 3 1 1 5 6}. If Eva’s favorite colors are given in her favorite order as {2 3 1 5 6}, then she has 4 possible best solutions {2 2 1 1 1 5 6}, {2 2 1 5 5 5 6}, {2 2 1 5 5 6 6}, and {2 2 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}, and {2 2 3 1 1 5 6}长度都为7,且元素顺序是跟指定的数组 {2 3 1 5 6}一致的。
二、解题思路
其实乍一看感觉很像是动态规划中的经典案例:最长非降子序列。
仔细想想其实就是求最长子序列嘛,只不过这个子序列的规则不是相邻元素非降序,而是相邻元素的位置要和指定的数组中的相对位置一致。
因此用一个check数组在标记短数组的元素之间的相对位置,check[x][y]如果等于1,则表示x在y左侧,check[x][y]如果等于-1,则表示x在y右侧,如果为0,则表示x==y。
接下来就可以采用最长非降子序列的算法了,dp[i]表示以i结尾的子序列的长度,初始值是1。如果这个数a[i]不在子数组中,则不放到dp集合中进行考虑。不过在比较的时候,找出第i个数前面的check[a[j]][a[i]] != -1的j,然后就是打擂台法dp[i]=max(dp[i], dp[j]+1),dp[j]的长度加一。 详情参考下面代码:
三、AC代码
#include<bits/stdc++.h>
using namespace std;
template<typename T = int>
T read(){
T x;
cin >> x;
return x;
}
int main(){
int n =read(), m = read();
vector<int>v(m), book(n+1);
vector<vector<int>>check(n+1);
for(auto &i: check){
i.resize(n+1);
}
for(int i = 0; i < m; i++){
v[i] = read();
book[v[i]] = 1;
for(int j = 0; j < i; j++){
check[v[i]][v[j]] = -1; // v[i]在v[j]的左侧
check[v[j]][v[i]] = 1; // v[j]在v[i]的右侧
}
}
vector<int>a, dp;
int l = read();
for(int i = 0; i < l; i++){
int x = read();
if(!book[x])continue;
int y = 1;
for(int j = 0; j < a.size(); j++){
if(check[a[j]][x] != -1){
y = max(y, dp[j]+1);// 动态规划
}
}
a.push_back(x);
dp.push_back(y);
}
cout << *max_element(dp.begin(), dp.end()) << endl;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
文章来源: blog.csdn.net,作者:爱玲姐姐,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/jal517486222/article/details/100005818
- 点赞
- 收藏
- 关注作者
评论(0)