闲言: 一切讲解不清晰的算法博文== 磨炼读者自学能力
本文参考合唱团——2016网易内推编程题
题目: 合唱团(网易编程题)
有 n 个学生站成一排,每个学生有一个能力值,牛牛想从这 n 个学生中按照顺序选取 k 名学生,要求相邻两个学生的位置编号的差不超过 d,使得这 k 个学生的能力值的乘积最大,你能返回最大的乘积吗?
输入描述:
- 每个输入包含 1 个测试用例。每个测试数据的第一行包含一个整数 n ( 1 ≤ n ≤ 50 ) n (1 \leq n \leq 50) n(1≤n≤50),表示学生的个数,接下来的一行,包含 n 个整数,按顺序表示每个学生的能力值 a i a_i ai( − 50 ≤ a i ≤ 50 -50 \leq a_i \leq 50 −50≤ai≤50)。接下来的一行包含两个整数,k 和 d ( 1 ≤ k ≤ 10 , 1 ≤ d ≤ 50 ) d (1 \leq k \leq 10, 1 \leq d \leq 50) d(1≤k≤10,1≤d≤50)。
输出描述
- 输出一行表示最大的乘积
输入例子:
3
7 4 7
2 50
输出例子:
49
先修知识:
- 动态规划: 动态规划表面上很难,其实存在很简单的套路:当求解的问题满足以下两个条件时, 就应该使用动态规划:
- 主问题的答案 包含了 可分解的子问题答案 (也就是说,问题可以被递归的思想求解)
- 递归求解时, 很多子问题的答案会被多次重复利用
- 动态规划的本质思想就是递归, 但如果直接应用递归方法, 子问题的答案会被重复计算产生浪费, 同时递归更加耗费栈内存(具体为什么更加消耗栈内存, 需要额外了解函数调用过程中, 进程栈内存的管理方式), 所以通常用一个二维矩阵(表格)来保存不同子问题的答案, 避免重复计算。
题目难点:
- 元素有正有负
- 如何满足相邻元素的距离不超过d 的限制
巧妙地分解问题
-
给定n个元素, 寻找k 个元素使乘积最大,可以从这k 个元素中最后一个元素所在的位置入手来思考。
-
对于数组 a=【7,4,7】, 假如 k ( 所 需 元 素 个 数 ) k(所需元素个数) k(所需元素个数) =2, d ( 相 邻 元 素 的 最 大 编 号 差 ) d(相邻元素的最大编号差) d(相邻元素的最大编号差)=2. 如果假设 a[2] 为目标序列的最后一个元素时, 还需要在a[2] 之前的元素中,寻找到一个长度为 $k-1 $的乘积序列, 且该序列的最后一个元素a[p] 与a[2]的距离小于等于d, 即 2 − p < = d 2-p <=d

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



