近期的DP题

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)

你可能感兴趣的:(近期的DP题)