1:
找出n个数中最长的等差数列
例:1 3 5 6 8 9 10 12 13 14
三项以上的等差子数列包括:
1 3 5
1 5 9 13
3 6 9 12
3 8 13
5 9 13
6 8 10 12 14
其中6 8 10 12 14最长,长度为5
首先,排序是很容易想到的,但排序后该怎么做呢?
我们看一下等差数列的性质,发现两个不同的等差数列,首项和公差总有一个不同
而公差可以根据首项与第2项的差值得到
因此设f[i][j]为首项为a[i],第2项为a[j]的最长长度
若k为第3项,则f[i][j]=f[j][k]+1(从后往前转移!)
在根据等差数列的性质,a[j]*2=a[i]+a[k]
因此for循环枚举j,接着从j-1和j+1开始枚举i和k,将满足条件的转移即可
2:
将n个数分成互不相交的m个字段和,且总和最大(若m小于正数个数,输出正数的总和)
例:-2 11 -4 13 -5 6 -2
分2段,11,-4,13一段,6一段,总和26
设f[i][j]表示表示前 j 项所构成 i 子段的最大和,且必须包含着第j项
则分2种情况:
一:f[ i ][ j ] = f[ i ] [ j-1 ] + a[ j ] ,即把第j项融合到第 j-1 项的子段中,子段数没变
二:f[ i ][ j ] = max(f[ i-1 ] [ k ]) + a[ j ],(i-1<= k< j )
考虑到时间,可以把f[ i-1 ][ k ]用一个一维数组记录,两重循环即可
3:
有n个数,它们的范围在1到a[ i ]之间,问怎么安排能使所有相邻两数的绝对值之和最大
由于要是差值最大,因此每个数一定为1或a[ i ]
设f[ i ][ 0 ]为i选1,f[ i ][ 1 ]为i选a[ i ]
f[1][0] = f[1][1] = 0
f[i][0] = max(f[i-1][0], f[i-1][1] + abs(1-a[i-1]))
f[i][1] = max(f[i-1][1] + abs(a[i]-a[i-1]), f[i-1][0] + abs(a[i]-1))
复杂度为O(n)