网易 合唱团

有 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

/**
 * 数组存在负数,需要维护一个最小值mn[i][j]
 * mx[i][j]表示前i个人选了j个人并且以第i个人为结尾满足相邻位置差不大于d的最大值
 * mn[i][j]表示前i个人选了j个人并且以第i个人为结尾满足相邻位置差不大于d的最小值
 */
public class Main {

    private static long solve(int[] arr, int n, int k, int d) {
        long[][] mx = new long[n + 1][12];
        long[][] mn = new long[n + 1][12];
        long ans = Long.MIN_VALUE;
        for (int i = 1; i <= n; i++) {
            mx[i][1] = arr[i - 1];
            mn[i][1] = arr[i - 1];
            for (int j = 2; j <= k; j++) {
                for (int x = i - 1; x >= Math.max(1, i - d); x--) {
                    long t_mx = mx[x][j - 1] * arr[i - 1];
                    long t_mn = mn[x][j - 1] * arr[i - 1];
                    mx[i][j] = Math.max(mx[i][j], Math.max(t_mx, t_mn));
                    mn[i][j] = Math.min(mn[i][j], Math.min(t_mx, t_mn));
                }
            }
            ans = Math.max(ans, mx[i][k]);
        }
        return ans;
    }

    public static void main(String[] arg) {
        Scanner scan = new Scanner(System.in);
        while (scan.hasNext()) {
            int n = scan.nextInt();
            int[] arr = new int[n];
            for (int i = 0; i < n; i++) {
                arr[i] = scan.nextInt();
            }
            int k = scan.nextInt();
            int d = scan.nextInt();
            System.out.println(solve(arr, n, k, d));

        }
        scan.close();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值