Given an array, we partition a row of numbers A into at most K adjacent (non-empty) groups, then the score is the sum of the average of each group. What is the maximum score than can be scored ?

Examples:

Input : A = { 9, 1, 2, 3, 9 }

K = 3

Output : 20

Explanation : We can partition A into [9], [1, 2, 3], [9]. The answer is 9 + (1 + 2 + 3) / 3 + 9 = 20.

We could have also partitioned A into [9, 1], [2], [3, 9]. That partition would lead to a score of 5 + 2 + 6 = 13, which is worse.Input : A[] = { 1, 2, 3, 4, 5, 6, 7 }

K = 4

Output : 20.5

Explanation : We can partition A into [1, 2, 3, 4], [5], [6], [7]. The answer is 2.5 + 5 + 6 + 7 = 20.5.

A simple solution is to use recursion. An efficient solution is memorization where we keep the largest score upto k i.e. for 1, 2, 3… upto k;

Let memo[i][k] be the best score portioning A[i..n-1] into at most K parts. In the first group, we partition A[i..n-1] into A[i..j-1] and A[j..n-1], then our candidate partition has score average(i, j) + score(j, k-1)), where average(i, j) = (A[i] + A[i+1] + … + A[j-1]) / (j – i). We take the highest score of these.

In total, our recursion in the general case is :

memo[n][k] = max(memo[n][k], score(memo, i, A, k-1) + average(i, j))

for all i from n-1 to 1 .

`// CPP program for maximum average sum partition ` `#include <bits/stdc++.h> ` `using` `namespace` `std; ` ` ` `#define MAX 1000 ` ` ` `double` `memo[MAX][MAX]; ` ` ` `// bottom up approach to calculate score ` `double` `score(` `int` `n, vector<` `int` `>& A, ` `int` `k) ` `{ ` ` ` `if` `(memo[n][k] > 0) ` ` ` `return` `memo[n][k]; ` ` ` `double` `sum = 0; ` ` ` `for` `(` `int` `i = n - 1; i > 0; i--) { ` ` ` `sum += A[i]; ` ` ` `memo[n][k] = max(memo[n][k], score(i, A, k - 1) + ` ` ` `sum / (n - i)); ` ` ` `} ` ` ` `return` `memo[n][k]; ` `} ` ` ` `double` `largestSumOfAverages(vector<` `int` `>& A, ` `int` `K) ` `{ ` ` ` `int` `n = A.size(); ` ` ` `double` `sum = 0; ` ` ` `memset` `(memo, 0.0, ` `sizeof` `(memo)); ` ` ` `for` `(` `int` `i = 0; i < n; i++) { ` ` ` `sum += A[i]; ` ` ` ` ` `// storing averages from starting to each i ; ` ` ` `memo[i + 1][1] = sum / (i + 1); ` ` ` `} ` ` ` `return` `score(n, A, K); ` `} ` ` ` `int` `main() ` `{ ` ` ` `vector<` `int` `> A = { 9, 1, 2, 3, 9 }; ` ` ` `int` `K = 3; ` `// atmost partioning size ` ` ` `cout << largestSumOfAverages(A, K) << endl; ` ` ` `return` `0; ` `} ` |

**Output:**

20

Above problem can now be easily understood as dynamic programming.

Let dp(i, k) be the best score partioning A[i:j] into at most K parts. If the first group we partition A[i:j] into ends before j, then our candidate partition has score average(i, j) + dp(j, k-1)). Recursion in the general case is dp(i, k) = max(average(i, N), (average(i, j) + dp(j, k-1))). We can precompute the prefix sums for fast execution of out code.

`// CPP program for maximum average sum partition ` `#include <bits/stdc++.h> ` `using` `namespace` `std; ` ` ` `double` `largestSumOfAverages(vector<` `int` `>& A, ` `int` `K) ` `{ ` ` ` `int` `n = A.size(); ` ` ` ` ` `// storing prefix sums ` ` ` `double` `pre_sum[n+1]; ` ` ` `pre_sum[0] = 0; ` ` ` `for` `(` `int` `i = 0; i < n; i++) ` ` ` `pre_sum[i + 1] = pre_sum[i] + A[i]; ` ` ` ` ` `// for each i to n storing averages ` ` ` `double` `dp[n] = {0}; ` ` ` `double` `sum = 0; ` ` ` `for` `(` `int` `i = 0; i < n; i++) ` ` ` `dp[i] = (pre_sum[n] - pre_sum[i]) / (n - i); ` ` ` ` ` `for` `(` `int` `k = 0; k < K - 1; k++) ` ` ` `for` `(` `int` `i = 0; i < n; i++) ` ` ` `for` `(` `int` `j = i + 1; j < n; j++) ` ` ` `dp[i] = max(dp[i], (pre_sum[j] - ` ` ` `pre_sum[i]) / (j - i) + dp[j]); ` ` ` ` ` `return` `dp[0]; ` `} ` ` ` `// Driver code ` `int` `main() ` `{ ` ` ` `vector<` `int` `> A = { 9, 1, 2, 3, 9 }; ` ` ` `int` `K = 3; ` `// atmost partioning size ` ` ` `cout << largestSumOfAverages(A, K) << endl; ` ` ` `return` `0; ` `} ` |

**Output:**

20

## Recommended Posts:

- Maximize array elements upto given number
- Maximum and Minimum Values of an Algebraic Expression
- Maximum subarray sum in O(n) using prefix sum
- K maximum sums of non-overlapping contiguous sub-arrays
- Lobb Number
- Number of ways to insert a character to increase the LCS by one
- Maximum difference of zeros and ones in binary string
- The painter's partition problem
- Divide an array into k segments to maximize maximum of segment minimums
- Divide array into two sub-arrays such that their averages are equal
- Find a partition point in array
- Maximum sum subarray removing at most one element
- Count Derangements (Permutation such that no element appears in its original position)
- Cutting a Rod | DP-13
- Coin Change | DP-7

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.