牛客网合唱队

题目:

有 n 个学生站成一排,每个学生有一个能力值,牛牛想从这 n 个学生中按照顺序选取 k 名学生,要求相邻两个学生的位置编号的差不超过 d,使得这 k 个学生的能力值的乘积最大,你能返回最大的乘积吗? 
输入描述:
每个输入包含 1 个测试用例。每个测试数据的第一行包含一个整数 n (1 <= n <= 50),表示学生的个数,接下来的一行,包含 n 个整数,按顺序表示每个学生的能力值 ai(-50 <= ai <= 50)。接下来的一行包含两个整数,k 和 d (1 <= k <= 10, 1 <= d <= 50)。


我本来想着很简单,然后写了动规,结果发现只得了40分,然后就开始了漫长的bug发现。竟然发现状态转移方程写错了。学习了!!


下面是错误的状态转移方程,第二个是正确的。


这个题总是不对,6.7成测试点都不对,有时间再改一该

package javapack;


import java.util.Scanner;

public class TMp {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            int n = sc.nextInt();
            int[] a = new int[n + 1];
            for (int i = 1; i < n + 1; i++) {
                a[i] = sc.nextInt();
            }
            int k = sc.nextInt();
            int d = sc.nextInt();
            int[][] dp = new int[k + 1][n + 1];
            for (int i = 0; i < k + 1; i++)
                dp[i][0] = 1;
            for (int i = 0; i < n + 1; i++)
                dp[0][i] = 1;
            int[][] dpvice = new int[k + 1][n + 1];
            for (int i = 0; i < k + 1; i++)
                dpvice[i][0] = 1;
            for (int i = 0; i < n + 1; i++)
                dpvice[0][i] = 1;
            for (int i = 1; i < k + 1; i++) {
                for (int j = 1; j < n + 1; j++) {
                    if (i == j)
                        dpvice[i][j] = dp[i][j] = Integer.MIN_VALUE;
                    else
                        dpvice[i][j] = dp[i][j] = dp[i][j - 1];
                    for (int h = 1; (j - h) >= 0 && h <= d; h++) {
                        if (dp[i - 1][j - h] * a[j] > dp[i][j])
                            dp[i][j] = dp[i - 1][j - h] * a[j];
                        if (dpvice[i - 1][j - h] * a[j] > dp[i][j])
                            dp[i][j] = dpvice[i - 1][j - h] * a[j];
                        if (dp[i - 1][j - h] * a[j] < dpvice[i][j])
                            dpvice[i][j] = dp[i - 1][j - h] * a[j];
                        if (dpvice[i - 1][j - h] * a[j] < dpvice[i][j])
                            dpvice[i][j] = dpvice[i - 1][j - h] * a[j];
                    }
                }
            }
            System.out.println(dp[k][n]);
        }
    }

}




正确的:

import java.util.Scanner;

public class TMp {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		while (sc.hasNext()) {
			int n = sc.nextInt();
			long[] a = new long[n + 1];
			for (int i = 1; i < n + 1; i++) {
				a[i] = sc.nextLong();
			}
			int k = sc.nextInt();
			int d = sc.nextInt();
			long[][] dp = new long[k + 1][n + 1];
			long[][] dpvice = new long[k + 1][n + 1];
			for (int i = 1; i < n + 1; i++)
				dp[1][i]=dpvice[1][i] = a[i];
			for (int i = 2; i < k + 1; i++) {
				for (int j = i; j < n + 1; j++) {
					dp[i][j] = dpvice[i][j] = dp[i-1][j-1]*a[j];
					for(int h = 1 ; h <= d&&(j-h)>=(i-1) ; h++){
						dp[i][j] = Math.max(dp[i][j], Math.max(dp[i-1][j-h]*a[j],dpvice[i-1][j-h]*a[j]));
						dpvice[i][j] = Math.min(dpvice[i][j], Math.min(dp[i-1][j-h]*a[j], dpvice[i-1][j-h]*a[j]));
					}
				}
			}
			long max = dp[k][1];
			for(int i = 2 ; i <= n ; i ++){
				max = Math.max(max, dp[k][i]);
			}
			System.out.println(max);
		}
	}
}





测试样例:

一、 

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

二、

 3
 7 4 7
 2 50

三、

你可能感兴趣的:(动规)