NKOJP1704——【Pugnacious 模拟赛II】tech的密码

问题描述

/*寂静的星期三…………
   Nicole半夜去机房刷完题后,突然发现tech的U盘没有带走……
   果然,上面有“动物世界”“入党申请书”“毛主席选集”“金刚葫芦娃”“英语听力材料”“走进科学”等很可疑的压缩包,但是狡猾的tech都设了密码。
   历尽千辛万苦,Nicole发现一个文本文档,里面有很多数。*/前面可忽视
   确切的说,一共有N行,每一行有M个数字。这些数字都是1到M的一个排列。
   只是这些数全部都是有规律的,最后的密码肯定是这M列数字里面的某一列。而这一列的序号,是这N行数字的最长上升公共子序列的长度!!当然,你只需要告诉Nicole这个长度即可。

输入格式

第一行2个空格隔开的正整数N和M
   接下来N行,每行M个数,保证这M个数全部是1~M的一个排列。

输出格式

一个数,如题目所述。

样例输入

2 7
1 2 3 5 7 6 4
1 7 2 6 3 4 5

样例输出

4

提示

数据范围:
   对于100%的数据,有N<=100,M<=200
   
   说明:
   1 2 3 4和1 2 3 5均可。


还记得怎么求两个序列的最长上升公共子序列吗?

如果不记得:

停🤚!你先学会求两个序列的最长上升公共子序列(如果懂请忽略)


当你懂之后

你一定会想到:不就是多几个序列吗?

对于100%的数据,有N<=100,M<=200

n <= 100,你肯定开不出100维的数组吧

于是你需要换思路。

首先,你要注意到一个与其他题不一样的一点:

 保证这M个数全部是1~M的一个排列

排列” 是什么意思?

指的是一个长度为n的序列由1~n这些数组成,每个数都出现一次。

比如n = 3

(1,2,3),(1,3,2),(2,1,3),(2,3,1),(3,1,2),(3,2,1)

这些就是n个数1~n排列

而(1,1,2),(3,3,2)就不是

所以,题目保证

• 每个序列都是1到M的排列!
• 每个数在每个序列中只出现一次!

然后,我们照常设定状态:f[x]表示以x为结尾的最长上升公共子序列当长度

状态转移if (y <= x - 1) f[x] = f[y] + 1 (即每个序列中y都在x左边)

•既然要确定方位,我们就要再开一个数组p[i][x],表示在第i个序列中值为x的位置

可得无论在哪个序列中,在y <= x - 1的情况下,p[i][y] 必须小于 p[i][x]

(why?)


!请仔细思考5分钟  !

 


因为

  保证这M个数全部是1~M的一个排列

每个数字仅,也必须出现一次,所以当y < x 但p[i][y] >= p[i][x],也就是y在i序列中在x之后时,x之前就不会有y,这样以x为结尾的n个序列的最长上升公共子序列就不成立 

举个例子:

        n = 3;(共3个序列)m = 4(长度为4)

        分别为:

        1,3,2,4

        1,4,2,3

        4,2,3,1

        假设x为此时的2,y = 1;在第三个序列中,1在2之后,很明显以2结尾的最长上升公共子序列就不能包含1

        


于是,你要循环判断,是不是每个序列都满足条件

for (int y = x - 1; y >= 1; y--) {
	if (f[x] <= f[y]) {
		bool flag = 1;
		for (int i = 1; i <= n; i++) {
			if (p[i][y] > p[i][x]) {
				flag = 0;
			}
		}
		if (flag) {
			f[x] = f[y] + 1;
		}
	}
}

(当没有y满足相对应的x时,f[x] = 1,所以可以在循环开头初始化

f[x] = 1;

最终答案 ans = max(ans, f[x])

那么,时间复杂度呢?

O(n^2*m),没有问题


    想要完整代码??

没门儿!!


THE END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值