版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37667021/article/details/82258889
网易_合唱团
题目描述
有 n 个学生站成一排,每个学生有一个能力值,牛牛想从这 n 个学生中按照顺序选取 k 名学生,要求相邻两个学生的位置编号的差不超过 d,使得这 k 个学生的能力值的乘积最大,你能返回最大的乘积吗?
输入描述:
每个输入包含 1 个测试用例。每个测试数据的第一行包含一个整数 n (1 <= n <= 50),表示学生的个数,接下来的一行,包含 n 个整数,按顺序表示每个学生的能力值 ai(-50 <= ai <= 50)。接下来的一行包含两个整数,k 和 d (1 <= k <= 10, 1 <= d <= 50)。
输出描述:
输出一行表示最大的乘积。
输入
3
7 4 7
2 50
输出
49
思路如下:
要求是从一个数组中顺序挑选出k个数,使得这k个数之乘积最大,但这k个数在数组中的位置编号的差不超过 d。
可以用maxVal[i][j]表示以j位置上的数为选的最后一个数,选择i个数的时候的最大值。这个题可以这样想,假如正在选第i个数,那么 maxVal[i][j]=ability[j]*maxVal[i-1][m],因为maxVal[i][j]本身就以j位置上的数为最后一个数,即j上面的必选,然后再乘上以前第i-1次时的结果就是现在的结果。第i个数时j上的数,那么第i-1个数就是从j位置向前推的距离不超过d的这些数其中一个,所以递推公式应该是 maxVal[i][j]=Math.max(maxVal[i][j], ability[j]*maxVal[i-1][m]);m表示着距离j不超过d的中的一个。由于数组中存在负数,那么我们不仅仅需要记录最大值,还要记录最小值, minVal[i][j]=Math.min(minVal[i][j], ability[j]*minVal[i-1][m]);
解释一下这个for循环:
for(i=2;i<=n;++i) {
for(j=0;j<n;++j) {
start=j-d;
if(start<0)start=0;
for(m=j-1;m>=start;m--){.....}
}
}
第一层先是确定找第i个数,第i个数的范围是0到n-1,即确定选的最后一个数是j,然后这 minVal[i][j] 的最大值由第 j 个上的数乘以选择的第i-1个数决定,故第3层循环是j前的d个数,可以从前往后遍历,也可以从后往前遍历,没有区别,因为ability[j]*minVal[i-1][m]中乘的是i-1层的数。以下这两个代买只是循环顺序不一样,只是为了理解才写的
代码一:
import java.util.*;
public class Main {
public static void main(String args[]) {
int i,j,k,n,d,m;
int[]ability=new int[60];
Scanner cin=new Scanner(System.in);
int start;
while(cin.hasNextInt()) {
n=cin.nextInt();
for(i=0;i<n;++i)
ability[i]=cin.nextInt();
k=cin.nextInt();
d=cin.nextInt();
long [][]maxVal=new long[60][60];
long[][]minVal=new long[60][60];
long ans=0;
for(i=0;i<n;++i) {
maxVal[1][i]=ability[i];
ans=Math.max(ans,ability[i]);
minVal[1][i]=ability[i];
}
for(i=2;i<=n;++i) {
for(j=0;j<n;++j) {
start=j-d;
if(start<0)start=0;
for(m=j-1;m>=start;m--)
{
maxVal[i][j]=Math.max(maxVal[i][j], ability[j]*maxVal[i-1][m]);
maxVal[i][j]=Math.max(maxVal[i][j], ability[j]*minVal[i-1][m]);
minVal[i][j]=Math.min(minVal[i][j], ability[j]*minVal[i-1][m]);
minVal[i][j]=Math.min(minVal[i][j], ability[j]*maxVal[i-1][m]);
}
if(i==k)ans=Math.max(ans,maxVal[k][j]);
}
}
System.out.println(ans);
}
}
}
/*
36
7 -15 31 49 -44 35 44 -47 -23 15 -11 10 -21 10 -13 0 -20 -36 22 -13 -39 -39 -31 -13 -27 -43 -6 40 5 -47 35 -8 24 -31 -24 -1
3 31
*/
代码二:
import java.util.*;
public class Main {
public static void main(String args[]) {
int i,j,k,n,d,m;
int[]ability=new int[60];
Scanner cin=new Scanner(System.in);
int start;
while(cin.hasNextInt()) {
n=cin.nextInt();
for(i=0;i<n;++i)
ability[i]=cin.nextInt();
k=cin.nextInt();
d=cin.nextInt();
long [][]maxVal=new long[60][60];
long[][]minVal=new long[60][60];
long ans=0;
for(i=0;i<n;++i) {
maxVal[1][i]=ability[i];
ans=Math.max(ans,ability[i]);
minVal[1][i]=ability[i];
}
for(i=2;i<=n;++i) {
for(j=0;j<n;++j) {
start=j-d;
if(start<0)start=0;
for(m=start;m<=j-1;m++)
{
maxVal[i][j]=Math.max(maxVal[i][j], ability[j]*maxVal[i-1][m]);
maxVal[i][j]=Math.max(maxVal[i][j], ability[j]*minVal[i-1][m]);
minVal[i][j]=Math.min(minVal[i][j], ability[j]*minVal[i-1][m]);
minVal[i][j]=Math.min(minVal[i][j], ability[j]*maxVal[i-1][m]);
}
if(i==k)ans=Math.max(ans,maxVal[k][j]);
}
}
System.out.println(ans);
}
}
}
/*
3
7 4 7
2 50
47
-41 -5 -10 -31 -44 -16 -3 -33 -34 -35 -44 -44 -25 -48 -16 -32 -37 -8 -33 -30 -6 -18 -26 -37 -40 -30 -50 -32 -5 -41 -32 -12 -33 -22 -14 -34 -1 -41 -45 -8 -39 -27 -23 -45 -10 -50 -34
6 3
*/