合唱团
有 n 个学生站成一排,每个学生有一个能力值,牛牛想从这 n 个学生中按照顺序选取 k 名学生,要求相邻两个学生的位置编号的差不超过 d,使得这 k 个学生的能力值的乘积最大,你能返回最大的乘积吗?
网址:http://www.nowcoder.com/questionTerminal/661c49118ca241909add3a11c96408c8
……想了半天,居然想不出来如何解释状态转移方程是怎么想出来的。这只能说,是套路。
这个思考过程待填,下面直接说状态的定义。
f [ i ] [ j ] [ 最大 / 最小 ]
分别表示,以第i个人为最后一个(也是必选的)人,加上这个人,已经选了 j 个人,最大可能的乘积和最小可能的乘积。
——为什么不是只记录最大的,还要记录最小的?
——因为最小的,很可能是一个负数,有着极大的绝对值,再乘一个负数,就变成最大的正数,也就是最优解了。
然后考虑,这个状态由哪些状态转移过来?
j 人,明显是从j-1个人的状态,最后加1个人(当前考虑的 i )而来。
第 i 人,根据题目要求,编号差不能大于d。那我们就往前观察最多d个人,从i-d到i-1,选了j-1个人中,选择和自己相乘,最大/最小的。
注意考虑边界条件:只选了一个人,就是 i 自己。
最后,解很大,请使用long long(C++)/ long (Java、C#)来保存中间计算结果。