Each input file contains one test case. For each case, the first line contains a positive integer N (<=200) which is the total number of colors involved (and hence the colors are numbered from 1 to N). Then the next line starts with a positive integer M (<=200) followed by M Eva's favorite color numbers given in her favorite order. Finally the third line starts with a positive integer L (<=10000) which is the length of the given stripe, followed by L colors on the stripe. All the numbers in a line are separated by a space.
For each test case, simply print in a line the maximum length of Eva's favorite stripe.
6 5 2 3 1 5 6 12 2 2 4 1 5 5 6 3 1 1 5 6
7
//一开始用dfs结果超时了
//然后发现这很像动态规划问题的最长公共子串问题,只有稍微改改转移方式就行了,难怪才2星难度
//状态转移根据左边和上边的值来确定,所以下标加1,0行初始化为0.
/*转移矩阵 序 0 1 2 3 4 5 6 7 8 9 10 11 12
色 2 2 4 1 5 5 6 3 1 1 5 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 0 1 2 2 2 2 2 2 2 2 2 2 2
2 3 0 1 2 2 2 2 2 2 3 3 3 3 3
3 1 0 1 2 2 3 3 3 3 3 4 5 5 5
4 5 0 1 2 2 3 4 5 5 5 5 5 6 6
5 6 0 1 2 2 3 4 6 6 6 6 6 6 7
*/
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
int N;
cin>>N;
int M;
cin>>M;
vector<int> order(M);
for(int i=0;i<M;i++){
cin>>order[i];
}
int K;
cin>>K;
vector<int> stripe(K);
for(int i=0;i<K;i++){
cin>>stripe[i];
}
vector<vector<int>> dp(M+1,vector<int>(K+1,0));
for(int i=0;i<M;i++){
for(int j=0;j<K;j++){
dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);
if(order[i]==stripe[j])dp[i+1][j+1]++;
}
}
cout<<dp.back().back();
return 0;
}
/**
* 题目:PAT_A-动规-中等-1045-最长有序序列
*
* 说明:
* 1. 输入:颜色种类N; 整数M, 喜爱颜色序列cl_fav[1,M]; 整数L, 原始布条序列cl_stripe[1,L]
* 2. 任务:喜爱颜色序列定义了颜色的顺序与合法与否,依此,找出最长有序序列(不一定连续)
* 3. 输出:最长有序序列长度
*
* 技巧:
* 1. 动态规划
* 2. 动态规划问题转化:
* DAG问题
* 3. 状态量表达(卡壳处):
* d[i] <=> 以cl_stripe[i]结尾(若可以)的喜爱布条的最长长度
* 所求结果 <=> max(d[i]), 枚举所有i
* 4. 决策种类:
* 详细见状态转移方程
* 5. 状态转移方程:
* d[i] = max(d[j] + 1), 枚举j满足<j,i>有向边存在,即喜爱颜色中j在i的左边
* 6. 程序实现:
* 终点表,迭代法,填表法
* 7. 注意!一定要让所有极端、边界情况都得到控制!让各个变量根据其含义在任何情况下都是正确的!
* 8. 本题的非喜爱颜色其实可以在一开始就剔除出cl_stripe[]
*
*/
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
#define MAXN 209
#define MAXM 209
#define MAXL 10009
int N;
int M;
int cl_fav[MAXM]; /* favourite colors */
int L;
int cl_stripe[MAXL]; /* colors of the stripe */
int id[MAXN]; /* id[cl_fav[i]] = i */
int d[MAXL]; /* d[i] <=> 以cl_stripe[i]结尾的喜爱布条的最长长度 */
int mxl_fs; /* maxlen of favourite stripe */
void init_all(void)
{
cin >> N;
cin >> M;
(void)memset(id, 0, sizeof(id));
for (int i = 1; i <= M; ++i) {
cin >> cl_fav[i];
id[cl_fav[i]] = i;
}
cin >> L;
for (int i = 1; i <= L; ++i) {
cin >> cl_stripe[i];
}
}
void solve_d(void)
{
for (int i = 1; i <= L; ++i) {
if (id[cl_stripe[i]] <= 0) {
d[i] = 0;
continue;
}
d[i] = 1;
for (int j = 1; j < i; ++j) {
if (id[cl_stripe[j]] <= 0) {
continue;
}
if (id[cl_stripe[i]] >= id[cl_stripe[j]]) {
d[i] = max(d[i], d[j] + 1);
}
}
}
mxl_fs = 0;
for (int i = 1; i <= L; ++i) {
mxl_fs = max(mxl_fs, d[i]);
}
}
int main(void)
{
(void)init_all();
(void)solve_d();
cout << mxl_fs;
return 0;
} input() b = dict(zip(input().split()[1:],range(1,201))) m = [0] + [0 for i in b] for i in [b[i] for i in input().split()[1:] if i in b]: m[i] = max(m[:i + 1]) + 1 print(max(m))
#include<iostream>
#include<vector>
#include<algorithm>
#define ARRAY vector<int> //下标从0开始有效
using namespace std;
int main(){
int likeNum, giveNum;
cin >> likeNum >> likeNum;
ARRAY like(likeNum, 0);
for (int i = 0; i < likeNum; i++) cin >> like[i];
cin >> giveNum;
ARRAY give(giveNum, 0);
for (int i = 0; i < giveNum; i++) cin >> give[i];
ARRAY dpArray(giveNum, 0);
for (int i = 0; i < likeNum; i++) {
for (int j = 0; j < giveNum; j++) {
dpArray[j] = max(dpArray[j == 0 ? 0 : j - 1], dpArray[j]) + (like[i] == give[j] ? 1 : 0);
}
}
cout << dpArray.back() << endl;
return 0;
} /*喜欢2 1 3 ,那么选中1后面就不能选2了,故序列改成1 2 3,
就是将输入数据按输入顺序改变其权值,转化成最长非递减子序列问题了
动态规划
dp思路:dp[i] 为0到第i项的最长非递减子序列长度。
dp[i] = max(dp[j])+1 a[j] < a[i]
这样是o(n^2),二分优化后 dp[i]保存的是长度为i时最长递增子序列的最小结尾 复杂度为nlogn。
*/
#include <bits/stdc++.h>
using namespace std;
const int AX = 1e4 + 666 ;
int b[206] ;
int dp[AX] ;
map<int,int>mp;
vector<int>a ;
int main() {
int n , m , k , x ;
scanf("%d",&k);
scanf("%d",&m);
for( int i = 1 ; i <= m ; i++ ) {
scanf("%d",&x);
mp[x] = i;
}
scanf("%d",&n);
for( int i = 0 ; i < n ; i++ ) {
scanf("%d",&x);
if(mp[x]) a.push_back(mp[x]);
}
dp[0] = a[0] ;
int tot = 0 ;
for( int i = 1 ; i < a.size() ; i++ ) {
if( a[i] >= dp[tot] ) {
dp[++tot] = a[i] ;
} else {
int pos = upper_bound( dp , dp + tot + 1 , a[i] ) - dp ;
dp[pos] = a[i] ;
}
}
printf("%d",tot+1);
return 0 ;
}
#include<stdio.h>
int order[204];
int num[10005];
int dp[10005];
int main()
{
int n;
while( scanf("%d",&n)!= EOF )
{
int x;
scanf("%d",&x);
for( int i = 0 ; i < x ; i++ )
scanf("%d",&order[i]);
int y;
scanf("%d",&y);
for( int i = 0 ; i < y ; i++ )
{
scanf("%d",&num[i]);
dp[i] = 0;
}
//按照喜欢颜色的顺序标号
//标号即为选择该位置颜色时最长序列
for( int i = 0 ; i < x ; i++ )
{
int max = 0;
for( int j = 0 ; j < y ; j++ )
{
if( order[i] == num[j] )
{
dp[j] = ++max;
}
else
{
if( dp[j] > max )
max = dp[j];
}
}
}
//选择最长序列
int ans = 0;
for( int i = 0 ; i < y ; i++ )
{
if( dp[i] > ans )
ans = dp[i];
}
printf("%d\n",ans);
}
return 0;
} #include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<vector>
using namespace std;
int main()
{
vector<int> origins;
int hashtable[210];
memset(hashtable,-1,sizeof(hashtable));
int N,N1,M;
scanf("%d",&N);
scanf("%d",&N1);
for(int i=0;i<N1;i++)
{
int tmp;
scanf("%d",&tmp);
hashtable[tmp] = i;
}
scanf("%d",&M);
for(int i=0;i<M;i++)
{
int tmp;
scanf("%d",&tmp);
if(hashtable[tmp]!=-1)
{
origins.push_back(hashtable[tmp]);
}
}
//然后最长不下降
int dp[10010];
dp[0]=1;
for(int i=0;i<origins.size();i++)
{
dp[i] = 1;
}
for(int i=0;i<origins.size();i++)
{
for(int j=i+1;j<origins.size();j++)
{
if(origins[j]>=origins[i]&&dp[i]+1>dp[j])
{
dp[j] = dp[i]+1;
}
}
}
int max = dp[0];
for(int i=1;i<origins.size();i++)
{
if(dp[i]>max)
max = dp[i];
}
cout<<max<<endl;
return 0;
}
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 203;
const int MAXL = 10003;
int a[MAXN], stripe[MAXL];
int dp[MAXN][MAXL] = {0};
int main()
{ int n,m,l,Max=0; cin>>n>>m; for(int i=0;i<m;i++) cin>>a[i]; cin>>l; for(int i=0;i<l;i++) cin>>stripe[i]; for(int i=0;i<m;i++) for(int j=0;j<l;j++) { dp[i+1][j+1] = max(dp[i][j+1], dp[i+1][j]); if(a[i] == stripe[j]) dp[i+1][j+1]++; Max = max(Max, dp[i+1][j+1]); } cout<<Max<<endl; return 0;
}
#include <iostream> #include <vector> using namespace std; int main() { ios::sync_with_stdio(false); // 读入数据 int N, M, L; cin >> N >> M; vector<int> fc(M+1); for(int i=1; i<=M; i++) cin >> fc[i]; cin >> L; vector<int> stripe(L+1); for(int i=1; i<=L; i++) cin >> stripe[i]; // 动态规划处理 vector<vector<int> > dp(M+1, vector<int>(L+1, 0)); for(int i=1; i<=M; i++) { for(int j=1; j<=L; j++) { dp[i][j] = max(dp[i-1][j-1], dp[i][j-1]); if(stripe[j] == fc[i]) { dp[i][j]++; } dp[i][j] = max(dp[i][j], dp[i-1][j]); } } cout << dp[M][L] << endl; return 0; }
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int N = 205;
const int M = 205;
const int L = 10005;
int n, m, l;
int favorite[N];
int original[L];
int dp[L][M];
void debug() {
for (int i = 1; i <= l; i++) {
for (int j = 1; j <= m; j++) {
printf("dp[%d][%d] = %d\n", i, j, dp[i][j]);
}
}
}
int main() {
#ifdef LOCAL
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
cin >> n;
cin >> m;
for (int i = 1; i <= m; i++) cin >> favorite[i];
cin >> l;
for (int i = 1; i <= l; i++) cin >> original[i];
for (int i = 1; i <= l; i++) {
for (int j = 1; j <= m; j++) {
dp[i][j] = dp[i - 1][j];
if (original[i] == favorite[j]) {
for (int k = 1; k <= j; k++) {
dp[i][j] = max(dp[i][j], dp[i - 1][k] + 1);
}
}
}
}
// debug();
int ans = 0;
for (int i = 1; i <= m; i++) ans = max(ans, dp[l][i]);
cout << ans << endl;
return 0;
} #include<cstdio>
int n,m,L,color,ans=-1,dp[500],pos[500];
int main(){
scanf("%d", &n);
scanf("%d", &m);
for(int i=1;i<=m;i++){
scanf("%d", &color);
pos[color]=i;
}
scanf("%d", &L);
for(int i=0;i<L;i++){
scanf("%d", &color);
if(pos[color]!=0){
int Max=-1,Pos=pos[color];
for(int j=1;j<=Pos;j++)
if(dp[j]>=Max)
Max=dp[j]+1;
dp[Pos]=Max;
if(dp[Pos]>ans) ans=dp[Pos];
}
}
printf("%d", ans);
return 0;
} #include<bits/stdc++.h>
using namespace std;
#define color int
int main() {
int N, M, L;
cin >> N >> M;
color n[M];
map<color, int> find_color;
for (int m = 0; m < 205; ++m) {
find_color[m] = -1;
}
for (int i = 0; i < M; ++i) {
cin >> n[i];
find_color[n[i]] = i;
}
cin >> L;
color l[L];
for (int j = 0; j < L; ++j)
cin >> l[j];
vector<int> longest(M, 0);
for (int k = 0; k < L; ++k) {
if(find_color[l[k]] != -1) {
int max = -1;
for (int i = 0; i <= find_color[l[k]]; ++i) {
if(longest[i] > max) {
max = longest[i];
}
}
longest[find_color[l[k]]] = max + 1;
}
}
// 以最后一个元素结尾不一定是最长的:cout << *(longest.end() - 1) << endl;
cout << *max_element(longest.begin(), longest.end()) << endl;
return 0;
}
//我就是个*****,开始把题目看错了,哪个实例以为favorite color为6,恰好能对应上,然后看她喜欢的颜色居然有重复,把我给整懵了 //然后小技巧,存优先级时将直接将stripes换成对应的优先级,这样就变成求最长不减序列。 //看到有大神说用最长公共序列,设喜欢的颜色顺序为fc数组,彩带颜色为stripe数组。 //把fc竖着排,把stripe横着排//dp[i][j]表示以颜色fc[i]和stripe[j]结尾的最大长度// dp[i][j] = max(dp[i-1][j], dp[i-1][j])+1 当fc[i]== stripe[j]时// dp[i][j] max(dp[i-1][j], dp[i][j-1]) 当fc[i]!= stripe[j]时 //dp[i][j-1]表示按照颜色喜好下标从0到i,彩带长度为j-1的时候所能得到的最大长度。 //因此可以直到当彩带长度增加1时,即dp[i][j]一定大于等于dp[i][j-1]。而且当fc[i]==stripes[j]时增加1。 //dp[i-1][j]表示按照颜色喜好下标从0到i-1,彩带长度为j的时候所能得到的最大长度。 //因此可以看出当fc再增加一个的时候,即dp[i][j]也大于等于dp[i-1][j],当fc[i]=stripes[j]时增加1。#include<iostream> (720)#include<vector> #include<algorithm> (831)#include<map> using namespace std; const int maxn = 201; int main() { int m, n, x; cin >> n; vector<int>favorite; map<int, int>mymap; cin >> n; for (int i = 1; i <= n; i++) { cin >> x; mymap[x] = i; favorite.push_back(x); } int num; vector<int>stripes; cin >> num; for (int i = 0; i < num; i++) { cin >> x; if (mymap[x])//去除掉不喜欢的颜色 stripes.push_back(mymap[x]);//直接将优先级当做彩带颜色!!! } vector<int>dp(num); dp[0] = 1; for (int i = 1; i < stripes.size(); i++) { dp[i] = -1; bool flag = false; for (int j = 0; j < i; j++) { if (stripes[i] >= stripes[j]) {//单调不减 dp[i] = max(dp[i], dp[j] + 1); flag = true; } } if (!flag) { dp[i] = 1; } } int max = -1; for (int i = 0; i < stripes.size(); i++) { if (dp[i] > max) { max = dp[i]; } } printf("%d", max); }
#include<iostream>
using namespace std;
int n, m,temp,l,seq[200],len[200];
bool has[201];
int main() {
cin >> n >> m;
for (int i = 0; i < m; i++) {
cin >> temp;
has[temp] = true;
seq[i] = temp;
}
cin >> l;
for (int i = 0; i < l; i++) {
cin >> temp;
if (has[temp]) {
int max = len[0];
for (int j = 0; j < m; j++) {
if (len[j] > max) max = len[j];
if (seq[j] == temp) len[j] = max + 1;
}
}
else {
l--; i--;
}
}
int max = len[0];
for (int i = 0; i < m; i++) if (max < len[i]) max = len[i];
cout << max;
return 0;
} #include<iostream>
using namespace std;
int N,M,L,tp,sq[201],pos[201],dp[201],colors[10001];
int main(){
cin>>N>>M;
for(int i = 1 ; i <= M ; i++){
cin >> tp;
pos[tp] = i;//颜色tp在喜欢的序列中的位置
sq[i] = tp;//喜欢的第i种颜色是tp
}
cin >> L;
for(int i = 1; i <= L; i++){
cin>>colors[i];
}
for(int i = 1; i <= L; i++){
int c = colors[i];
if(pos[c] != 0){//若该颜色在喜欢的序列中
int subMax = 0;
for(int j = 1; j <= pos[c]; j++){
subMax = max(subMax,dp[sq[j]]);//找到前面的最长序列
}
dp[c] = subMax + 1;//dp数组表示以下标c结尾的最长序列的长度
}
}
int res = 0;
for(int i = 1 ;i <= N ;i ++){
res = max(dp[i],res);//比较得出最大的长度
}
cout<<res;
return 0;
} #include<iostream>
#include<vector>
using namespace std;
vector<int>ar;
int dep[10000] = { 0 }, pri[210] = { 0 }, n, m, total, tem,maxd=1;
int main()
{ cin >> total >> m; for (int i = 0; i < m; i++) { cin >> tem; pri[tem] = 200 - i; } cin >> n; for (int i = 0; i < n; i++) { cin >> tem; if (pri[tem] > 0)ar.push_back(tem); } dep[0] = 1; for (int i = 1; i < ar.size(); i++) { dep[i] = 1; for (int j = 0; j < i; j++) { if (pri[ar[j]] >= pri[ar[i]] && dep[j] + 1 > dep[i]) { dep[i] = dep[j] + 1; if (dep[i] > maxd)maxd = dep[i]; } } } cout << maxd;
return 0;
}
优雅解决 最低空间负责度#include <bits/stdc++.h>using namespace std;inta[202],b[202],c[202];intmain(){intn,m,l,box,ans=0;scanf("%d %d",&n,&m);memset(b,-1,sizeof(b));for(inti=0;i<m;i++){scanf("%d",&a[i]);b[a[i]]=i;}scanf("%d",&l);for(inti=0;i<l;i++){scanf("%d",&box);intmaxx=0;if(b[box]!=-1){for(intj=0;j<=b[box];j++)maxx=max(c[a[j]],maxx);}c[box]=maxx+1;ans=max(c[box],ans);}printf("%d\n",ans);return0;}
N=int(input())
A=list(map(int,input().split()[1:]))
B=list(map(int,input().split()[1:]))
F=[[0]*len(B) for _ in range(len(A)+1)]
for i in range(1,len(A)+1):
for j in range(len(B)):
F[i][j]=max(F[i-1][j],F[i][j-1])
F[i][j]+=1 if A[I-1]==B[j] else 0
print(F[len(A)][len(B)-1]) #include<iostream>
#include<cstdio>
using namespace std;
int love[10010];
//求最长不下降子序列
int color[10010];
int dp[10010];
int main()
{
freopen("data.in","r",stdin);
int nn,n;
cin>>nn>>n;
for(int i=1;i<=n;i++)
{
int t;
cin>>t;
love[t]=i;
}
int L,num=0;
cin>>L;
for(int i=0;i<L;i++)
{
int c;
cin>>c;
if(love[c]>0)
color[num++]=love[c];
}
for(int i=0;i<num;i++)
{
dp[i]=1;
for(int j=0;j<i;j++)
{
if(color[j]<=color[i] && dp[i]<dp[j]+1)
dp[i]=dp[j]+1;
}
}
int k=0;
for(int i=0;i<num;i++)
{
if(dp[k]<dp[i])
k=i;
}
cout<<dp[k];
return 0;
}