题目描述
有 n 个学生站成一排,每个学生有一个能力值,牛牛想从这 n 个学生中按照顺序选取 k 名学生,要求相邻两个学生的位置编号的差不超过 d,使得这 k 个学生的能力值的乘积最大,你能返回最大的乘积吗?
输入描述:
每个输入包含 1 个测试用例。每个测试数据的第一行包含一个整数 n (1 <= n <= 50),表示学生的个数,接下来的一行,包含 n 个整数,按顺序表示每个学生的能力值 ai(-50 <= ai <= 50)。接下来的一行包含两个整数,k 和 d (1 <= k <= 10, 1 <= d <= 50)。
输出描述:
输出一行表示最大的乘积。
示例1
输入
3
7 4 7
2 50
输出
49
import java.util.Scanner;
//动态规划
public class Main {
private static int[] val;//能力值
private static int d;//相邻两个同学的位置差不超过d
private static long[][][] dp;//dp[6][4][0]代表顺序选出4位同学,其中末位同学为为6(同学编号从0开始),乘积最小值
//dp[6][4][1]代表顺序选出4位同学,其中末位同学为为6(同学编号从0开始),乘积最大值
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int n = s.nextInt();
val = new int[n];
for (int i = 0; i < n; i++) {
val[i] = s.nextInt();
}
int k = s.nextInt();
d = s.nextInt();
s.close();
dp = new long[n][Math.min(n + 1, 11)][2];
for (int i = 0; i < n; i++) {
dp[i][1][0] = dp[i][1][1] = val[i];
}
for (int i = 2; i < Math.min(n + 1, 11); i++) {
for (int j = i - 1; j < n; j++) {
long[] res = getResult(j, i - 1);
dp[j][i][1] = val[j] > 0 ? res[1] * val[j] : res[0] * val[j];
dp[j][i][0] = val[j] > 0 ? res[0] * val[j] : res[1] * val[j];
}
}
long max = dp[k - 1][k][1];
for (int i = k; i < n; i++) {
if (max < dp[i][k][1])
max = dp[i][k][1];
}
System.out.println(max);
return;
}
private static long[] getResult(int index, int cnt) {
int down = Math.max(cnt - 1, index - d);
long res[] = new long[2];
res[1] = dp[down][cnt][1];
res[0] = dp[down][cnt][0];
for (int i = down + 1; i < index; i++) {
if (res[1] < dp[i][cnt][1])
res[1] = dp[i][cnt][1];
if (res[0] > dp[i][cnt][0])
res[0] = dp[i][cnt][0];
}
return res;
}
}
题目来源于牛客网