UVA 111 History Grading (最长公共子序列)


History Grading
Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu

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. 1 point for each event whose rank matches its correct rank
  2. 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


这道题,不用多说,最长公共子序列

刚开始,看到只用第二条规则求解以后,想到的就是公共子序列,然后就开始敲代码,把最长公共子序列的代码敲好,运行,测试,在 Sample Input1 中结果完全匹配的输出,提交, WA~~~~~~  ,甚是感觉郁闷,开始找错,看了几遍代码确定最长公共子序列写的有没错, 然后就测试 Sample Input2 这组数据,结果连测试数据都没过,感觉更郁闷了,回来看第二条,没错啊,就是最长公共子序列啊,然后就有开始重新读题,看看是不是哪点理解错了,连蒙带猜的读了两遍题,还是没发现什么(英语不好是硬伤啊),再继续读,就这样又读了一会,又想了想,最后终于发现了,原来他给的顺序说的是第 i 个事件是在第几发生的,就像以前做的排序题那样,,,唉:-(    ,给跪了,都可以这样子,然后就改了改代码,提交,AC,(⊙o⊙)哦,真不 容易啊,一道最长公共子序列活生生的写了两个多小时~~~~~~~~~~~~~慢慢的都是泪啊~~~~~~~~~~~~~~!

题意大概就是说,给你 1 到 n 个事件,按照第一行的序列排序后与按照其他行序列排序后的最长公共子序列是多少。



附上代码:


#include 
#include 
#include 
#include 
#include 
#include 
#define INF 0x3f3f3f3f
#define MAX_N 100

using namespace std;

int num[MAX_N];
int dp[MAX_N][MAX_N];

int main()
{
	int n;
	cin >> n;
	for(int i = 1;i <= n;i++)
	{
		int k;
		cin >> k;
		num[k] = i;          //  按照给的顺序排列下
	}
	int a[MAX_N];
	int c;
	memset(dp,0,sizeof(dp));
	while(cin >> c)
	{
		a[c] = 1;
		for(int i = 2;i <= n;i++)
		{
			cin >> c;
			a[c] = i;             //   按照给的顺序排列下
		}
		for(int i = 1;i <= n;i++)        // dp求最长公共子序列
		{
			for(int j = 1;j <= n;j++)
			{
				if(num[i] == a[j])
				{
					dp[i + 1][j + 1] = dp[i][j] + 1;
				}
				else
				dp[i + 1][j + 1] = max(dp[i][j + 1],dp[i + 1][j]);
			}
		}
		cout << dp[n + 1][n + 1] << endl;
	}
	return 0;
}


你可能感兴趣的:(【动态规划】,【C/c++,知识点】)