思路:
首先想到动态规划,解描述为f(n,k),那子问题是什么呢?假设是这样的形式f(n-i, k-1)。但子问题最优并不意味着问题最优,因为ai的取值有正有负,所以动态规划不可行。那只能用遍历全部组合,比较选出乘积的最大值,幸亏题目里的n和k的大小是有约束。
(1)首先想到一个问题k个值相乘,可能会溢出,大概计算一下乘积的上界:50的10次方=9.7*(10的16次方),所以存储乘积的变量要用long long,long long 的上限时2的63次方。
(2)要采用递归遍历,递归的终止条件是按照约束取完k个数,然后比较乘积。
(3)边界条件:
边界1:第一个元素的位置p1决定后边k-1个的位置,p1<=n-k。
边界2:当取到第j个元素时,j的位置pj,设start=pj-1 ,end=start+d,那么pj的取值范围是start+1
<=pj<=end,如果end>=n, 那么end=n-1。
边界3:当取到第j个元素时,起始位置是start,目前未取的点数为kj,如果start+kj>n,该取法无效,返回。
下面直接贴代码:
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
long long result=1;
void Multiply(vector<int> weight, int start, int k, int d, long long ji){
if(k==0){
result=result>ji?result:ji;
return;
}
if(start+k>=weight.size())
return;
int end=start+d;
if(end>=weight.size())
end=weight.size()-1;
start+=1;
for(int i= start; i<=end; i++){
Multiply(weight,i,k-1,d,ji*weight[i]);
}
}
int main(){
int n=5;
int b[]={7,8,9,10,11};
int k=4;
int d=50;
long long ji=1;
vector<int> weight(b,b+5);
for(int i=0; i<n; i++)//result初始化为最小负数
result*=-50;
if(result>0)
result*=-50;
for(int i=0; i<=weight.size()-k; i++)
Multiply(weight, i, k-1, d, ji*weight[i]);
cout<<result<<endl;
return 0;
}