UVa 111|History Grading|动态规划|最长上升子序列

来源:互联网 发布:网贷平台数据分析 编辑:程序博客网 时间:2024/05/16 03:24

题目

计算机科学中的许多问题涉及有约束的最优化问题。
考虑一个要求学生按时间顺序排序历史事件的历史考试。排序正确的学生将获得满分,但是只对了一部分的学生要怎么给分呢?
有以下一些可能:
1. 和正确答案对应相同的事件个数为其分数
2. 和正确答案相似程度最大的子序列(不要求连续)的长度为其分数。
举个例子,如果4个事件的正确顺序是1 2 3 4,那么答案1 3 2 4按第一种方法将获得2分(1和4事件对应上了);按第二种方法将获得3分(1 2 4之间的顺序是对的,或者1 3 4)。
为了最大化学生的成绩,减少他们对评分标准的不满,老师决定选用第2种方案作为评分标准。请你写一个程序实现它。
给定n个事件的正确顺序用c1,c2,,cn表示,其中ci为第i个事件的按时间顺序的名次
给定学生的答案r1,r2,,rn,**其中rn表示学生认为第i个事件应该的排名是多少。
输出按第二种方案的评分。

输入

输入第一行一个整数n(2n20),表示历史事件的个数。
第二行包含n个整数ci
接下来每行n个整数表示多个学生的ri。一行一个学生的答案。
EOF结束。

输出

对每个学生,输出一行一个整数,表示该学生的得分。

注意

请注意关键字眼:顺序和名次。

样例输入1

44 2 3 11 3 2 43 2 1 42 3 4 1

样例输出1

123

样例输入2

103 1 2 4 9 5 10 6 8 71 2 3 4 5 6 7 8 9 104 7 2 3 10 6 9 1 5 83 1 2 4 9 5 10 6 8 72 10 1 3 8 4 9 5 7 6

样例输出2

65109

题解

很显然,将名次转换为原来的历史事件的id的话,与标准答案的最长公共子序列的长度就是答案,但是本题比较特别,原序列和新序列都不重复不缺漏地包含[1..n]的所有数字,因此本题可以转化为最长上升子序列解决。

#include <cstdio>#include <cstring>#include <algorithm>#define FOR(i,j,k) for(i=j;i<=k;++i)using namespace std;int f[32], a[32], dp[32];int main() {    int n, i, j, k, ans;    scanf("%d", &n);    FOR(i,1,n) scanf("%d", &k), f[i] = k;    while (1) {        FOR(i,1,n)             if (scanf("%d", &k) == EOF)                return 0;            else                a[k] = f[i];        memset(dp, 0, sizeof dp);        dp[1] = 1; a[0] = 0; ans = 0;        FOR(i,2,n) FOR(j,0,i-1)            if (a[i] > a[j])                dp[i] = max(dp[i], dp[j] + 1);        FOR(i,1,n) ans = max(ans, dp[i]);        printf("%d\n", ans);    }    return 0;}
阅读全文
0 0
原创粉丝点击