CF463D Gargari and Permutations(dp lcs)

题目

题目描述
Gargari got bored to play with the bishops and now, after solving the problem about them, he is trying to do math homework. In a math book he have found k k permutations. Each of them consists of numbers 1 , 2 , . . . , n 1,2,...,n 1,2,...,nin some order. Now he should find the length of the longest common subsequence of these permutations. Can you help Gargari?

You can read about longest common subsequence there:
输入格式
The first line contains two integers n and k ( 1 < = n < = 1000 ; 2 < = k < = 5 ) k (1<=n<=1000; 2<=k<=5) k(1<=n<=1000;2<=k<=5) . Each of the next k k k lines contains integers 1 , 2 , . . . , n 1,2,...,n 1,2,...,n in some order — description of the current permutation.

输出格式
Print the length of the longest common subsequence.

题意翻译
题目描述
给你k个长度为n的排列,求这些排列的最长公共子序列的长度

输入格式
第一行包含 n ( 1 < = n < = 1000 ) n(1<=n<=1000) n(1<=n<=1000) k ( 2 < = k < = 5 ) k(2<=k<=5) k(2<=k<=5)。 后面的 k k k行分别表示 k k k个排列。

输出格式
输出最长公共子序列的长度

说明
第一个测试样本的答案是子序列 [ 1 , 2 , 3 ] [1,2,3] [1,2,3]

输入输出样例
输入 #1
4 3
1 4 2 3
4 1 2 3
1 2 4 3
输出 #1
3
说明/提示
The answer for the first test sample is subsequence [1, 2, 3].

题解

  • f [ x ] f[x] f[x]表示以 x x x结尾的合法的最大方案数
  • 显然只有当x出现k次并且x前面合法的数字(合法序列中的数字)都在x之前(原序列中)才可以状态转移

code

#include <bits/stdc++.h> 
using namespace std; 
const int maxn = 1e3 + 100; 

template <class T> 
inline void read(T &s) {
	s = 0; T w = 1, ch = getchar(); 
	while (!isdigit(ch)) { if (ch == '-') w = -1; ch = getchar(); }
	while (isdigit(ch)) { s = (s << 1) + (s << 3) + (ch ^ 48); ch = getchar(); }
	s *= w; 
}

int n, m, res = -1; 
int cnt[maxn], f[maxn]; 
int a[7][maxn], pos[7][maxn]; 
vector <int> v; 

int main() {
	read(n), read(m); 
	for (int i = 1; i <= m; ++i) {
		for (int j = 1; j <= n; ++j) {
			read(a[i][j]); 
			pos[i][a[i][j]] = j; 
		}
	}
	v.push_back(0); 
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= m; ++j) {
			int x = a[j][i]; 
			if (++cnt[x] != m) continue; 
			for (int k = 0; k < v.size(); ++k) {
				int y = v[k], flag = 1; 
				for (int l = 1; l <= m; ++l) {
					if (pos[l][x] <= pos[l][y]) {
						flag = 0; 
						break; 
					}
				}
				if (flag) {
					f[x] = max(f[x], f[y] + 1); 
					res = max(res, f[x]); 
				}
			}
			v.push_back(x); 
		}
	}
	printf("%d\n", res); 
	return 0; 
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值