动态规划算法题

题目描述(网易)

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

输入描述:

   每个输入包含 1 个测试用例。每个测试数据的第一行包含一个整数 n (1 <= n <= 50),表示学生的个数,接下来的一行,包含 n 个整数, 按顺序表示每个学生的能力值 ai(-50 <= ai <= 50)。接下来的一行包含两个整数,k 和 d (1 <= k <= 10, 1 <= d <= 50)。

输出描述:

输出一行表示最大的乘积。
本题要使用动态规划来解,动态规划的特点:1.求解的是最优化问题;2.可以分解为最优子结构
本题可以先求解在第i个学生的位置下,j(j<K)个学生的能力值的最大值,得到所有学生位置下j个学生的能力值的最大值;在j个学生的情况下,得到j+1个学生的最大值,最后得到k个学生的最大值,下面以一个例子来解释(注意因为有负数,所以要计算最小值,同时保存):
样例输出:
     10
     8 7 2 -7 9 5 4 10 -7 1
     3 3
输出:
   
630

如上,第一步先计算k=2的情况:
7:在d=3的情况下,最大最小值都为56
2:
在d=3的情况下,最大值为16,最小值为14
-7:在d=3的情况下,最大值为-14,最小值为-56
......
得到第一趟的结果

k=3的情况下(这里以第一趟的结果为基础,只有这样就不需要考虑第一趟中d=3的限制):
2:
在d=3的情况下,最大最小值都为112(56*2)
-7:
d=3的情况下,最大值为-98(14*-7)最小值为-392(56*-7)
9:
在d=3的情况下,最大值为504(56*9)最小值为-504(-56*9)
......
得到第二趟的结果

返回最大值就是最后的结果
#-*- coding:utf-8 -*-

n=input()
array=[int(i) for i in raw_input().split()]
k,d=[int(i) for i in raw_input().split()]
# n=36
array_max=array_min=array
#轮询k-1趟即可
for i in range(0,k-1):
    _max=[-float('inf')]*n#将最大值的数组赋值无穷小
    _min=[float('inf')]*n#将最小值的数组赋值无穷大
    for j in range(i+1,n):
        if j<=d+i:#下面对应的min、max都是考虑到array[j]为负值的情况下
            temp_max = max(max(ii*array[j] for ii in array_max[i:j]),max(ii*array[j] for ii in array_min[i:j]))
            temp_min = min(min(ii*array[j] for ii in array_max[i:j]),min(ii*array[j] for ii in array_min[i:j]))
        else:
            temp_max = max(max(ii*array[j] for ii in array_max[j-d:j]),max(ii*array[j] for ii in array_min[j-d:j]))
            temp_min = min(min(ii*array[j] for ii in array_max[j-d:j]),min(ii*array[j] for ii in array_min[j-d:j]))
        _max[j]=temp_max
        _min[j]=temp_min
    array_max=_max
    array_min=_min
    print array_max
    print array_min
print max(array_max)
 


 



猜你喜欢

转载自www.cnblogs.com/ybf-yyj/p/8880011.html