题目意思: 给定一个正确的编号序列,然后对输入的每一组序列找最长公共子序列
解题思路: 动态规划
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; }