今天是ACM课的小测验(也许称不上小测验),因为上大关心ACM的人实在太少了。一共有四道题目,三道是很简单的题目,最后一道比较经典的,有点曾经做旅行商问题时候的感觉。测试时,我自己并没有写出来,只是觉得是DP的方向,后来在老师的提示下通过了。
题目如下:
原本想到的DP是用p[i][j]记录a数组的0 - i个元素和b数组的0 - j个元素的最大匹配数,然后每次的p[i][j]值是这样算的:
t = match ( i , j ) // t 在i 能和b中某元素匹配且j 能和a中某元素匹配 时为2,不能匹配为0
p[ i ] [ j ] = max ( p[i-1][j] , p[i][j-1] ) +t
但是题目中的限制条件实在苛刻,比如两条线段不能从同一点出发,而且只有两条相交才能算是一对匹配,搞得我最后实在无法把match( i,j )函数写出来。
经老师点化后,才发觉这题其实只要理清思路,想到DP方程就变得很容易了:
p[ i ][ j ] = max ( p[i-1][j] , p[i][j-1] ,
for all m<i and n<j if( a[i]=b[n] && b[j]=a[m] ) get p[m][j]+2 )
虽然是四个循环,速度是慢了点,不过还是过了。得到的教训是分析比一味的打补丁要重要得多啦,多多学学DP吧。
题目如下:
整数匹配
Description
有两行正整数,第一行与第二行中相同的数可匹配,在它们之间画一条线段,如匹配的数为p,那么该线段叫p线段。求最大匹配数,要求满足:
(1)每条p匹配线段恰好和一条q-匹配线段相交(p<>q),
(2)不存在两条线段从一个数出发。
Input
第1行是整数t,表示t组测试数据,(1 <=t <= 20)。接着是这t组测试数据的描述。每组测试数据有3行,其第一行是2个整数m、n,第二行有m个整数a1,a2,…,am,第三行有n个整数b1, b2,…,bn,每行的整数之间有一个空格,(1 <=m,n <= 10000)。两组测试数据之间有一空行。
Output
对每组测试数据,首先在一行上输出“Case #:”,其中“#” 测试数据组号,从1开始编号。接着在同一行上输出这组数据之间的最大匹配数。
Sample Input
2
2 3
1 2
2 4 1
7 9
1 3 4 5 3 5 8
4 6 3 3 7 5 2 2 1
Sample Output
Case 1: 2
Case 2: 4
原本想到的DP是用p[i][j]记录a数组的0 - i个元素和b数组的0 - j个元素的最大匹配数,然后每次的p[i][j]值是这样算的:
t = match ( i , j ) // t 在i 能和b中某元素匹配且j 能和a中某元素匹配 时为2,不能匹配为0
p[ i ] [ j ] = max ( p[i-1][j] , p[i][j-1] ) +t
但是题目中的限制条件实在苛刻,比如两条线段不能从同一点出发,而且只有两条相交才能算是一对匹配,搞得我最后实在无法把match( i,j )函数写出来。
经老师点化后,才发觉这题其实只要理清思路,想到DP方程就变得很容易了:
p[ i ][ j ] = max ( p[i-1][j] , p[i][j-1] ,
for all m<i and n<j if( a[i]=b[n] && b[j]=a[m] ) get p[m][j]+2 )
虽然是四个循环,速度是慢了点,不过还是过了。得到的教训是分析比一味的打补丁要重要得多啦,多多学学DP吧。