uva111动态规划之最长公共子序列
Description
Background
Many problems in Computer Science involve maximizing some measure according to constraints.
Consider a history exam in which students are asked to put several historical events into chronological order. Students who order all the events correctly will receive full credit, but how should partial credit be awarded to students who incorrectly rank one or more of the historical events?
Some possibilities for partial credit include:
- 1 point for each event whose rank matches its correct rank
- 1 point for each event in the longest (not necessarily contiguous) sequence of events which are in the correct order relative to each other.
For example, if four events are correctly ordered 1 2 3 4 then the order 1 3 2 4 would receive a score of 2 using the first method (events 1 and 4 are correctly ranked) and a score of 3 using the second method (event sequences 1 2 4 and 1 3 4 are both in the correct order relative to each other).
In this problem you are asked to write a program to score such questions using the second method.
The Problem
Given the correct chronological order of n events as where denotes the ranking of event i in the correct chronological order and a sequence of student responses where denotes the chronological rank given by the student to event i; determine the length of the longest (not necessarily contiguous) sequence of events in the student responses that are in the correct chronological order relative to each other.
The Input
The first line of the input will consist of one integer n indicating the number of events with . The second line will contain nintegers, indicating the correct chronological order of n events. The remaining lines will each consist of n integers with each line representing a student's chronological ordering of the n events. All lines will contain n numbers in the range , with each number appearing exactly once per line, and with each number separated from other numbers on the same line by one or more spaces.
The Output
For each student ranking of events your program should print the score for that ranking. There should be one line of output for each student ranking.
Sample Input 1
4 4 2 3 1 1 3 2 4 3 2 1 4 2 3 4 1
Sample Output 1
1 2 3
Sample Input 2
10 3 1 2 4 9 5 10 6 8 7 1 2 3 4 5 6 7 8 9 10 4 7 2 3 10 6 9 1 5 8 3 1 2 4 9 5 10 6 8 7 2 10 1 3 8 4 9 5 7 6
Sample Output 2
6 5 10 9
最长公共子序列(Longest Common Subsequence)
问题大意 给定两个序列 A 和 B,求 A 和 B 的最长公共子序列。子序列即从最初序 列去除某些元素但不破坏余下元素的相对位置而得到的新序列 1。
对应题目 HOJ 1227 1316
分析 子序列是从原序列中去掉某些元素所得到的序列,注意到原序列前缀的子序列 也是原序列的子序列,而且如果要得到的公共子序列最长,那么把公共子序列的最后 一个元素去掉之后,所得的序列应该是 A 和 B 某个前缀的 LCS。例如 A = abcdabcd, B = acdbcdb,目测知 A 和 B 的最长公共子序列应该是 S = acdcd,假如把最后一个匹 配的 d 去掉,得到的 acdc 显然是 C = abcdabc 和 D = acdbc 的 LCS,否则如果 C、 D 存在更长的 LCS,那么这个 LCS 加上 d,得到了比 S 更长的串,且该串是 A 和 B 的 LCS。 有了这个结论,余下的问题就比较明显了,用 dp[i,j] 表示 A 的前 i 个字符与 B 的 前 j 个字符的 LCS,则有 dp[i,j] ={max(dp[i−1,j −1] + 1,dp[i−1,j],dp[i,j −1]), if A[i] = B[i] max(dp[i−1,j],dp[i,j −1]), if A[i] ̸= B[j] 边界和初值比较容易,这里不再说明。思考最后的答案的取值应该在哪里,对比一下方 格取数与 LCS 的不同。 时间和空间复杂度都是 O(n2)。
1 /* 2 【题目大意】 3 一个历史考试,有n个历史事件, 它们之间的年份是不同的,要学生把这些事件按照正确 4 的顺序排列出来。有两种记分方式, 5 采用的是第二种: 假设有历史事件1,2,3,4, 6 它们正确的时间顺序是1,2,3,4, 然后假设学生的答案是1,3,2,4, 那么按照相 7 对顺序正确的数量,答对了三个 8 (1,2,4或者1,3,4),也就是它与正确答案的最长 9 公共子序列长度是3,便是答对的数量。 10 11 【分析与总结】 12 最长公共子序列模板题,但是这题的输入是个很大的坑,他的输入是按照顺序,事件1是排在第几位, 13 事件2是排在第几位......, 所以要先把输入转换成正确的顺序。 14 15 【代码】 16 */ 17 #include<iostream> 18 #include<cstring> 19 #include<cstdio> 20 using namespace std; 21 int order[25], arr[25], d[25][25]; 22 23 int main() 24 { 25 int n, t; 26 scanf("%d",&n); 27 // 读入正确的答案顺序 28 for(int i=0; i<n; i++) 29 { 30 scanf("%d",&t); 31 order[t-1]=i+1; //放入他排名的位置,所以order就是正确的答案 32 } 33 while(scanf("%d",&t)!=EOF) 34 { 35 arr[t-1]=1; 36 for(int i=1; i<n; ++i) 37 { 38 scanf("%d",&t); 39 arr[t-1]=i+1; 40 } 41 // 求出最长公共子序列长度 42 memset(d, 0, sizeof(d)); 43 for(int i=0; i<n; ++i) 44 { 45 for(int j=0; j<n; ++j) 46 { 47 if(order[i]==arr[j]) 48 d[i+1][j+1]=max(max(d[i][j]+1,d[i][j+1]),d[i+1][j]); 49 else 50 d[i+1][j+1]=max(d[i][j+1],d[i+1][j]); 51 } 52 } 53 printf("%d\n", d[n][n]); 54 } 55 return 0; 56 }