Problem:
微生物発電

飯沼博士は磐梯山の噴気孔でふしぎな微生物を見つけました。この微生物の雄と雌１体ずつが合体すると、電気エネルギーを放出します。この微生物を研究すれば、将来のエネルギー危機から我々を救えるかもしれません。

観察を続けると、微生物は合体したときだけ電気エネルギーを発生させることと、合体した微生物のさらなる合体はないことがわかりました。さらに観察を続けると、合体で放出される電気エネルギーは、微生物が体内に持つ未知の粒子（博士はこれを磐梯山にちなんでＢ粒子と名づけました）の量で決まることがわかりました。合体する雄と雌が体内に持つＢ粒子の量をそれぞれ bm と bw とすると、合体により放出される電気エネルギーは |bm - bw| × (|bm - bw| - 30)2 という式で計算できます。

この発見により、微生物の集団から得られる最大の電気エネルギーが計算できるようになりました。それでは、微生物の集団に含まれる雄と雌の数と、各個体が持つＢ粒子の量が与えられたとき、この微生物の集団から得られる最大の電気エネルギーを計算するプログラムを作成してください。

入力

入力は複数のデータセットからなる。入力の終わりはゼロ2つの行で示される。入力データは以下の形式で与えられる。

M W
bm1 bm2 ... bmM
bw1 bw2 ... bwW

１行目の M と W (1 ≤ M,W ≤ 12) はそれぞれ雄と雌の微生物の数である。２行目に、i 番目の雄が体内に持つＢ粒子の量 bmi (0 ≤ bmi ≤ 50) が与えられる。３行目に、i 番目の雌が体内に持つＢ粒子の量 bwi (0 ≤ bwi ≤ 50) が与えられる。

データセットの数は 20 を超えない。

出力

データセットごとに、微生物の集団から得られる電気エネルギーの最大値を1行に出力する。

入出力例

入力例

3 3
0 20 30
10 20 30
10 10
32 10 15 8 20 10 6 45 50 41
18 0 37 25 45 11 25 21 32 27
7 3
23 14 39 6 47 16 23
19 37 8
0 0

出力例

12000
53906
11629

Solution in C# (judge verdict: Accepted)

using static System.Math;
using System;

public class Hello
{
    public static void Main()
    {
        while (true)
        {
            string[] line = Console.ReadLine().Trim().Split(' ');
            var m = int.Parse(line[0]);
            var w = int.Parse(line[1]);
            if (m == 0 && w == 0) break;
            line = Console.ReadLine().Trim().Split(' ');
            var bm = Array.ConvertAll(line, int.Parse);
            line = Console.ReadLine().Trim().Split(' ');
            var bw = Array.ConvertAll(line, int.Parse);
            var dp = new int[m + 1, 1 << w];
            for (int i = 0; i < m + 1; i++)
                for (int j = 0; j < (1 << w); j++) dp[i, j] = -1;
            var ans = goDP(dp, bm, bw, m, w);
            Console.WriteLine(ans);
        }
    }
    static int goDP(int[,] dp, int[] bm, int[] bw, int m, int w)
    {
        var ans = 0;
        dp[0, 0] = 0;
        var kmax = 1 << w;
        for (int i = 0; i < m; i++)
            for (int k = 0; k < kmax; k++)
            {
                if (dp[i, k] == -1) continue;
                dp[i + 1, k] = Max(dp[i + 1, k], dp[i, k]);
                for (int j = 0; j < w; j++)
                {
                    var ww = 1 << j;
                    if ((k & ww) >= 1) continue;
                    var t = (k | ww);
                    dp[i + 1, t] = Max(dp[i + 1, t], dp[i, k] + calcEP(bm[i], bw[j]));
                    ans = Max(ans, dp[i + 1, t]);
                }
            }
        return ans;
    }
    static int calcEP(int m, int b)
    {
        var w = Abs(m - b);
        return w * (w - 30) * (w - 30);
    }
}