Problem:
MathJax.Hub.Config({
tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}
});

D: スキャナー / Scanner

問題文

ここに $N$ 枚の紙がある。あなたは $3$ 台のスキャナーを並列に用いることで、
全ての紙をスキャンしたいと考えている。それぞれの紙はスキャンにかかる時間が決まっており、
$i$ 番目の紙をスキャンするのにかかる時間は $T_i$ である。
紙をスキャンする順番は任意であるが、$1$ 台のスキャナーで複数の紙を同時にスキャンすることはできない。

全ての紙のスキャンが終了し、スキャンを行っているスキャナーがなくなるまでにかかる時間を最小化しなさい。

入力

$N$

$T_1$

$T_2$

$T_3$

$\vdots$

$T_N$

制約

$1 \leq N \leq 50$

$1 \leq T_i \leq 50$

入力は全て整数

出力

答えを $1$ 行で出力してください．

サンプル

サンプル入力1

4
1
1
1
1

サンプル出力1

2

サンプル入力2

9
15
20
27
4
10
7
34
30
36

サンプル出力2

61

サンプル入力3

6
20
18
46
16
9
48

サンプル出力3

55

Solution in C# (judge verdict: Accepted)

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

class TEST{
	static void Main(){
		Sol mySol =new Sol();
		mySol.Solve();
	}
}

class Sol{
	public void Solve(){
		if(N==1){
			Console.WriteLine(A[0]);
			return;
		}
		
		int NN=900;
		bool[][] dp=new bool[NN][];
		for(int i=0;i<NN;i++)dp[i]=new bool[NN];
		
		dp[0][0]=true;
		int tot=0;
		for(int t=0;t<N;t++){
			for(int i=NN-1;i>=0;i--){
				for(int j=NN-1;j>=0;j--){
					if(dp[i][j]==false)continue;
					int a=i;
					int b=j;
					int c=tot-i-j;
					
					int[] aa;
					aa=new int[]{a+A[t],b,c};
					Array.Sort(aa);
					if(aa[1]<NN)dp[aa[0]][aa[1]]=true;
					aa=new int[]{a,b+A[t],c};
					Array.Sort(aa);
					if(aa[1]<NN)dp[aa[0]][aa[1]]=true;
					aa=new int[]{a,b,c+A[t]};
					Array.Sort(aa);
					if(aa[1]<NN)dp[aa[0]][aa[1]]=true;
				}
			}
			tot+=A[t];
		}
		
		
		int min=(int)1e9;
		for(int i=0;i<NN;i++){
			for(int j=0;j<NN;j++){
				if(dp[i][j]==false)continue;
				int a=i;
				int b=j;
				int c=tot-i-j;
					
				int[] aa;
				aa=new int[]{a,b,c};
				min=Math.Min(min,aa.Max());
			}
		}
		
		Console.WriteLine(min);
		
		
		
	}
	
	
	int N;
	int[] A;
	public Sol(){
		N=ri();
		A=new int[N];
		
		for(int i=0;i<N;i++)A[i]=ri();
	}

	static String rs(){return Console.ReadLine();}
	static int ri(){return int.Parse(Console.ReadLine());}
	static long rl(){return long.Parse(Console.ReadLine());}
	static double rd(){return double.Parse(Console.ReadLine());}
	static String[] rsa(char sep=' '){return Console.ReadLine().Split(sep);}
	static int[] ria(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>int.Parse(e));}
	static long[] rla(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>long.Parse(e));}
	static double[] rda(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>double.Parse(e));}
}