题目意思: 给定一个正确的编号序列,然后对输入的每一组序列找最长公共子序列
解题思路: 动态规划
1:题目给定的n个数并不是表示当前位置的值就是Ai,而是表示第i个数放在第Ai个位置,看样列4 2 3 1,说明1放在第四位,2放在第二位,3放在第三位,4放在第一位。
2:题目就是要求出最长的公共子序列,由于题目的n最大才20,那么我们可以直接去枚举。假设现在枚举到Ai这个数,那么我们就求i之前的所以数能够和Ai构成连续的序列最大值dp[i],然后判断能否更新最大值(max_point < dp[i]),最后输出这个最大值即可。
代码:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
using namespace std;
#define MAXN 25
int n;
int correct[25];//存储正确的顺序
int order[MAXN];//要求的顺序
int dp[MAXN];
void solve(){
int max_point = 0;
int pos_i , pos_j;//记录在correct数组中的位置
dp[0] = 1;
for(int i = 1 ; i < n ; i++){
dp[i] = 1;//初始化为1
for(int j = i-1 ; j >= 0 ;j--){//搜索i之前的数
for(int k = 0 ; k < n ; k++){//去correct数组中找到order[i] 和order[j]的位置
if(correct[k] == order[i]) pos_i = k;
if(correct[k] == order[j]) pos_j = k;
}
if(pos_i > pos_j){//如果i在j后面说明是连续的,求dp[i]
if(dp[j]+1 > dp[i]) dp[i] = dp[j]+1;
}
}
if(max_point < dp[i]) max_point = dp[i];//更新max_point
}
printf("%d\n" , max_point);
}
int main(){
//freopen("input.txt" , "r" , stdin);
int m;
scanf("%d" , &n);
for(int i = 1 ; i <= n ; i++){
scanf("%d" , &m) ; correct[m-1] = i;//求出correct数组
}
while(scanf("%d" , &m) != EOF){
order[m-1] = 1;
for(int j = 2 ; j <= n ; j++) {
scanf("%d" , &m) ; order[m-1] = j;//求出order数组
}
solve();
}
return 0;
}