题目大意:有n个历史事件,需要对他们按发生的时间先后进行排名。给出正确的排名顺序和学生排出的顺序,按学生答案中最长的正确相对顺序序列的长度给分,计算学生能得多少分。如正确顺序是1,2,3,4,学生答案为1,3,2,4,学生可得三分(123和134序列均可)。
就是求两个序列的最长公共序列(LCS),经典问题,要注意的就是题中给出的是事件的排名,要转化成排名后的事件序列。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 #define MAXN 25 6 7 int correct[MAXN], query[MAXN]; 8 int dp[MAXN][MAXN]; 9 10 int main() 11 { 12 #ifdef LOCAL 13 freopen("in", "r", stdin); 14 #endif 15 int n; 16 scanf("%d", &n); 17 int x; 18 for (int i = 1; i <= n; i++) 19 { 20 scanf("%d", &x); 21 correct[x] = i; 22 } 23 while (scanf("%d", &x) != EOF) 24 { 25 query[x] = 1; 26 for (int i = 2; i <= n; i++) 27 { 28 scanf("%d", &x); 29 query[x] = i; 30 } 31 memset(dp, 0, sizeof(dp)); 32 for (int i = 1; i <= n; i++) 33 for (int j = 1; j <= n; j++) 34 { 35 if (correct[i] == query[j]) dp[i][j] = dp[i-1][j-1] + 1; 36 else dp[i][j] = max(dp[i-1][j], dp[i][j-1]); 37 } 38 printf("%d\n", dp[n][n]); 39 } 40 return 0; 41 }