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

题意:
一个历史考试,有n个历史事件, 它们之间的年份是不同的,要学生把这些事件按照正确的顺序排列出来。
有两种记分方式,采用的是第二种: 假设有历史事件1,2,3,4, 它们正确的时间顺序是1,2,3,4, 然后假设学生的答案是1,3,2,4, 那么按照相对顺序正确的数量,答对了三个(1,2,4或者1,3,4),也就是它与正确答案的最长公共子序列长度是3,便是答对的数量。
请你求出答对的数量。

解析:最长公共子序列的模板题,但是请注意先要将序列进行转换。
原序列是按时间顺序的事项排列,所以给你的排列要转化一下:例如:
10
3 1 2 4 9 5 10 6 8 7
意思是:1事项在第三个时间位置发生,2事项在第一个时间发生,以此类推……
转化为:2 3 1 4 6 8 10 9 5 7

转换完后,按照最长公共子序列的模板求解。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 25;
int dp[N][N];
int goal[N];
int num[N];
int main() {
	int n,pos;
	scanf("%d",&n);
	for(int i = 1; i <= n; i++) {
		scanf("%d",&pos);
		goal[pos] = i;
	}
	while(scanf("%d",&pos) != EOF) {
		num[pos] = 1;
		for(int i = 2; i <= n; i++) {
			scanf("%d",&pos);
			num[pos] = i;
		}
		memset(dp,0,sizeof(dp));
		for(int i = 1; i <= n; i++) {
			for(int j = 1; j <= n; j++) {
				if(num[j] == goal[i]) {
					dp[i][j] = dp[i-1][j-1]+1;
				}else {
					dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
				}
			}
		}
		printf("%d\n",dp[n][n]);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值