Problem:
D: 水槽

問題

AORイカちゃんは縦 $1$ 横 $N$ の大きさの水槽をもらった。水槽は水を入れるのに十分な高さがある。
水槽には $N-1$ 個の仕切りがあり $N$ 個の区画に等間隔に区切られている。
ここに水を注いだところ、各区画の水の高さは $a_i$ になった。

AORイカちゃんはいくつか仕切りを取り除き、区画の数を $M$ 個以下にすることにした。
仕切りを取り除き終わった時、各区画の水の高さの総和の最大値を求めよ。

なお、仕切りの厚さは無視できるものとする。

制約

$1 \le N \le 500$

$1 \le M \le N$

$1 \le a_i \le 10^9$

入力は全て整数

入力

$N \ M$

$a_1 \cdots a_N$

出力

各区画の水の高さの総和の最大値を一行で出力せよ。また末尾に改行を出力せよ。
相対誤差または絶対誤差が $10^{-6}$ 以下であれば許容される。

サンプル

サンプル入力 1

5 3
9 1 2 3 9

サンプル出力 1

20.000000

$a_2$ と $a_3$ 、$a_3$ と $a_4$ の間の仕切りをとると、その区画の水の高さは $\frac{(1 + 2 + 3)}{3} = 2$ となる。
各区画の水の高さは $9 \ 2 \ 9$ となりこれが最大である。

サンプル入力 2

4 1
14 4 9 7

サンプル出力 2

8.500000

サンプル入力 3

8 3
11 18 9 20 4 18 12 14

サンプル出力 3

44.666667

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Globalization;
using System.Diagnostics;
using Pair = System.Collections.Generic.KeyValuePair<int, int>;

class Program
{
    static void Main()
    {
        //Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        new Program().Solve();
        Console.Out.Flush();
    }
    Scanner cin = new Scanner();


    void Solve()
    {
        int N = cin.Nextint;
        int M = cin.Nextint;
        var A = cin.Scanlong;
        var B = new long[N + 1];
        for (int i = 0; i < N; i++)
        {
            B[i + 1] = A[i] + B[i];
        }


        var dp = new double[N + 1][][];
        for (int i = 0; i < N + 1; i++)
        {
            dp[i] = new double[N + 1][];
            for (int j = 0; j < N + 1; j++)
            {
                dp[i][j] = new double[N + 1];
                for (int k = 0; k < N + 1; k++)
                {
                    dp[i][j][k] = int.MinValue;
                }
            }
        }
        dp[0][0][0] = 0;

        for (int i = 0; i <= N - 1; i++)
        {
            for (int j = 0; j <= i; j++)
            {
                for (int k = 0; k <= i; k++)
                {
                    dp[i + 1][j][k] = Math.Max(dp[i][j][k], dp[i + 1][j][k]);
                    dp[i + 1][j + 1][i + 1] = Math.Max(
                        dp[i][j][k] + (B[i + 1] - B[k]) / (double)(i + 1 - k), dp[i + 1][j + 1][i + 1]);
                }
            }
        }

        //double ans = 0;
        //for (int i = 0; i <= N; i++)
        //{
        //    Console.WriteLine(dp[N, i, N]);
        //    if (i <= M) ans = Math.Max(ans, dp[N, i, N]);
        //}
        Console.WriteLine(dp[N][M][N].ToString("F7"));
    }

}

class Scanner
{
    string[] s; int i;
    char[] cs = new char[] { ' ' };
    public Scanner() { s = new string[0]; i = 0; }
    public string[] Scan { get { return Console.ReadLine().Split(); } }
    public int[] Scanint { get { return Array.ConvertAll(Scan, int.Parse); } }
    public long[] Scanlong { get { return Array.ConvertAll(Scan, long.Parse); } }
    public double[] Scandouble { get { return Array.ConvertAll(Scan, double.Parse); } }
    public string Next
    {
        get
        {
            if (i < s.Length) return s[i++];
            string st = Console.ReadLine();
            while (st == "") st = Console.ReadLine();
            s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
            i = 0;
            return Next;
        }
    }
    public int Nextint { get { return int.Parse(Next); } }
    public long Nextlong { get { return long.Parse(Next); } }
    public double Nextdouble { get { return double.Parse(Next); } }
}