合唱团算法(DP问题)

题目:有 n 个学生站成一排,每个学生有一个能力值,牛牛想从这 n 个学生中按照顺序选取 k 名学生,要求相邻两个学生的位置编号的差不超过 d,使得这 k 个学生的能力值的乘积最大,你能返回最大的乘积吗?

类似于前面写到的LSI最长递增子序列,
    只不过这里控制了选取K个, 所以这里定义了一个最大数据结构fm[i][j] 其中表示选取了i+1个学生,以j结束(选取了j为结尾)最大值
    这里数组可能有负数,所以定义了一个最小数据结构fn[i][j]

        迭代的数据结构:

                fm[k][i] = max(fm[k][i],max(fm[k-1][j]*arr[i], fn[k-1][j]*arr[i]))

           fn[k][i] = min(fn[k][i],min(fm[k-1][j]*arr[i], fn[k-1][j]*arr[i]))

代码如下:
= int ( raw_input ())
arr  = map ( int , raw_input ().split())
K,D  = map ( int , raw_input ().split())
 
fm  = [ ([ 0 ] * n)  for in range (K) ]  # k*d
fn  = [ ([ 0 ] * n)  for in range (K) ]  # k*d
res = 0
 
for in range (n):
     fm[ 0 ][i] = arr[i]
     fn[ 0 ][i] = arr[i]
 
for in range (n):
     for in range ( 1 ,K):
         #for j in range(i-1,-1,-1):
         for in range (i - 1 , max ( 0 ,i - D) - 1 , - 1 ):
             #if (i-j<D and k>0):
                 fm[k][i]  = max (fm[k][i], max (fm[k - 1 ][j] * arr[i], fn[k - 1 ][j] * arr[i]))
                 fn[k][i]  = min (fn[k][i], min (fm[k - 1 ][j] * arr[i], fn[k - 1 ][j] * arr[i]))
                 #fm[k][i] = max(fm[0][i],max(fm[k-1][j]*arr[i], fn[k-1][j]*arr[i]))
                 #fn[k][i] = min(fn[0][i],min(fm[k-1][j]*arr[i], fn[k-1][j]*arr[i]))
                 #fm[k][i] = max(fm[k-1][j]*arr[i], fn[k-1][j]*arr[i])
                 #fn[k][i] = min(fm[k-1][j]*arr[i], fn[k-1][j]*arr[i])
     res = max (res,fm[K - 1 ][i])
print res

猜你喜欢

转载自blog.csdn.net/asdasdasdasasd1111/article/details/80904792