<此为小编分享对此题的理解,若涉及侵权行为,请通知小编下架>
这个题目我们采用动态规划的方法。动态规划在我的理解是把一个问题分为多个阶段去求解,即从下往上也可以从上往下地递推。
这个题目我们可以看作是从下往上的递推。我们是要求n个学生中选k个学生的能力值乘积最大,假设我们现在知道了n个学生中选k-1个学生的能力值乘积的最大值x,那么我们只需要在剩下的学生中找到能力值与x相乘最大的学生。
如:求出n个学生中选1个学生的最大值,可以求出n个学生中选2个学生的最大值…求出n个学生中选k个学生的最大值。
代码分析:
定义一个二维数组f[n][k],n表示总人数,k表示选取的人数,代码中的left用于寻找第k-1个学生的位置。
注意点1:能力值有可能为负数,所以定义第二个二维数组,用于存放每次运算得到的最小值。最小值若与下一个负数相乘可能为最大值。
注意点2:数组下标是从0开始的,需要注意数组下标不能等于n,k。
import java.util.Scanner;
public class Main {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext())
{
int n = sc.nextInt();//总人数
int[] arr = new int[n];//存储能力值
for(int i=0;i<n;i++)
{
arr[i] = sc.nextInt();
}
int k = sc.nextInt();//总选取人数
int d = sc.nextInt();//间隔
long[][] f = new long[n][k];
long[][] g = new long[n][k];
int last;//最后一个人的位置
int k1;//选取人数
int left;//第last-1个人的位置
for(last=0;last<n;last++)//倘若选取人数为1
{
f[last][0]=arr[last];
g[last][0]=arr[last];
}
for(k1=1;k1<k;k1++)//确定选取人数
{
for(last=k1;last<n;last++)//确定最后一个人的位置
{
long max = Long.MIN_VALUE;
long min = Long.MAX_VALUE;
for(left=Math.max(k1-1,last-d);left<=last-1;left++)//left为第last-1个人的位置开始寻找第k个学生的位置
{
if(max<Math.max(f[left][k1-1]*arr[last],g[left][k1-1]*arr[last]))//两个数组分别与第k个学生相乘,求最大的那个值
{
max = Math.max(f[left][k1-1]*arr[last],g[left][k1-1]*arr[last]);
}
if(min>Math.min(f[left][k1-1]*arr[last],g[left][k1-1]*arr[last]))
{
min = Math.min(f[left][k1-1]*arr[last],g[left][k1-1]*arr[last]);
}
}
f[last][k1] = max;//确定last为最后一个学生时,能力的最大值为max
g[last][k1] = min;//确定last为最后一个学生时,能力的最小值为max
}
}
long result = Long.MIN_VALUE;
//在选取人数大于1后,f[last][k]的意思是last个学生中选取的k个学生的能力值乘积的最大值
for(last=k-1;last<n;last++)//确定last在区间(k-1,n-1)的最大值,最后一个学生的下标为n-1
{
if(result<f[last][k-1])
{
result = f[last][k-1];
}
}
System.out.println(result);
}
}
}