一、问题
https://leetcode-cn.com/problems/largest-sum-of-averages/solution/
我们将给定的数组 A 分成 K 个相邻的非空子数组 ,我们的分数由每个子数组内的平均值的总和构成。计算我们所能得到的最大分数是多少。 注意我们必须使用 A 数组中的每一个数进行分组,并且分数不一定需要是整数。 示例: 输入: A = [9,1,2,3,9] K = 3 输出: 20 解释: A 的最优分组是[9], [1, 2, 3], [9]. 得到的分数是 9 + (1 + 2 + 3) / 3 + 9 = 20. 我们也可以把 A 分成[9, 1], [2], [3, 9]. 这样的分组得到的分数为 5 + 2 + 6 = 13, 但不是最大值. 说明: 1 <= A.length <= 100. 1 <= A[i] <= 10000. 1 <= K <= A.length. 答案误差在 10^-6 内被视为是正确的。
二、GitHub实现:https://github.com/JonathanZxxxx/LeetCode/blob/master/Class813.cs
Blog:https://www.cnblogs.com/zxxxx/
三、思路:动态规划
1、dp[i,k]视为将数组前i个元素分为k个子数组得到的最大的分数,dp[i,k]的值通过dp[j,k-1]得来,状态转移方程dp[i,k]=max(dp[i,k],dp[j,k-1]+(sum[j]-sum[i])/(j-i)),其中1<=j<i,sum[i]
为数组前i个元素的总和
2、涉及到三个维度的变化,数组长度从1到最大,k的长度从1到最大K,子数组的长度j从1到当前数组长度i-1
四、代码
public double LargestSumOfAverages(int[] A, int K) { var sum = new int[A.Length + 1]; for (int i = 0; i < A.Length; i++) { sum[i + 1] = sum[i] + A[i]; } var dp = new double[A.Length + 1, K + 1]; for (int i = 1; i <= A.Length; i++) { dp[i, 1] = (double)sum[i] / i; for (int k = 2; k <= K && k <= i; k++) { for (int j = 1; j < i; j++) { dp[i, k] = Math.Max(dp[i, k], dp[j, k - 1] + (double)(sum[i] - sum[j]) / (i - j)); } } } return dp[A.Length, K]; }