Problem:
パティシエ

ケーキ屋さんが、まちまちな大きさのロールケーキをたくさん作りました。あなたは、このケーキを箱に並べる仕事を任されました。

ロールケーキはとてもやわらかいので、他のロールケーキが上に乗るとつぶれてしまいます。ですから、図(a) のように全てのロールケーキは必ず箱の底面に接しているように並べなければなりません。並べ替えると必要な幅も変わります。

図(a)

図(b)

n 個のロールケーキの半径 r1, r2, ..., rn と箱の長さを読み込み、それぞれについて、箱の中にうまく収まるかどうか判定し、並べる順番を工夫すると箱に入る場合は "OK"、どう並べても入らない場合には "NA"を出力するプログラムを作成してください。

ロールケーキの断面は円であり、箱の壁の高さは十分に高いものとします。 ただし、ロールケーキの半径は 3 以上 10 以下の整数とします。つまり、ケーキの半径に極端な差はなく、図(b) のように大きなケーキの間に小さなケーキがはまり込んでしまうことはありません。

Input

入力は複数のデータセットからなります。各データセットは以下の形式で与えられます。

W r1 r2 ... rn

最初に箱の長さを表す整数 W (1 ≤ W ≤ 1,000) が与えられます。 続いて、空白区切りで各ロールケーキの半径を表す整数 ri (3 ≤ ri ≤ 10) が与えられます。ケーキの個数 n は 12 以下です。

データセットの数は 50 を超えません。

Output

データセットごとに OK または NA を１行に出力してください。

Sample Input

30 4 5 6
30 5 5 5
50 3 3 3 10 10
49 3 3 3 10 10

Output for the Sample Input

OK
OK
OK
NA

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace _0120
{
    public class Program

    {
        public static void Main(string[] args)
        {
            while (true)
            {

                string line = Console.ReadLine();
                if (string.IsNullOrEmpty(line)) return;

                int[] items = Array.ConvertAll(line.Trim().Split(' '), e => int.Parse(e));
                int w = items[0];
                int[] r = items.Skip(1).ToArray();

                int n = r.Length;
                double[,] dp = new double[(1 << n), n];
                for (int i = 0 ; i < dp.GetLength(0) ; i++)
                {
                    for (int j = 0 ; j < dp.GetLength(1) ; j++)
                    {
                        dp[i, j] = int.MaxValue;
                    }
                }

                for (int i = 0 ; i < dp.GetLength(0) ; i++)
                {
                    for (int j = 0 ; j < n ; j++)
                    {
                        if (i == 0)
                        {
                            dp[(1 << j), j] = Math.Min(dp[(1 << j), j], r[j]);
                        }
                        else
                        {
                            for (int k = 0 ; k < dp.GetLength(1) ; k++)
                            {
                                if (dp[i, k] == int.MaxValue) continue;

                                int next = i | (1 << j);
                                dp[next, j] = Math.Min(dp[next, j], dp[i, k] + getDistance(r[k], r[j]));
                            }
                        }
                    }
                }

                double ans = double.MaxValue;
                for (int i = 0 ; i < n ; i++) ans = Math.Min(ans, dp[(1 << n) - 1, i] + r[i]);
                Console.WriteLine(ans - 1e-8 <= w ? "OK" : "NA");
            }
        }

        public static double getDistance(double r1, double r2)
        {
            return 2 * Math.Sqrt(r1 * r2);
        }


        static string RSt() { return Console.ReadLine(); }
        static int RInt() { return int.Parse(Console.ReadLine().Trim()); }
        static long RLong() { return long.Parse(Console.ReadLine().Trim()); }
        static double RDouble() { return double.Parse(Console.ReadLine()); }
        static string[] RStAr(char sep = ' ') { return Console.ReadLine().Trim().Split(sep); }
        static int[] RIntAr(char sep = ' ') { return Array.ConvertAll(Console.ReadLine().Trim().Split(sep), e => int.Parse(e)); }
        static long[] RLongAr(char sep = ' ') { return Array.ConvertAll(Console.ReadLine().Trim().Split(sep), e => long.Parse(e)); }
        static double[] RDoubleAr(char sep = ' ') { return Array.ConvertAll(Console.ReadLine().Trim().Split(sep), e => double.Parse(e)); }
        static string WAr<T>(IEnumerable<T> array, string sep = " ") { return string.Join(sep, array.Select(x => x.ToString()).ToArray()); }
    }

}