import std.stdio, std.conv, std.string, std.bigint;
import std.math, std.random, std.datetime;
import std.array, std.range, std.algorithm, std.container, std.format;
string read(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }

/*

ゲーム 
区間DP

------------

左をi個、右をj個とった状態からの先手(＝次の人)の得点 x[i][j]

i + j == n のとき
	x[i][j] = 0

i + j + 1 == n のとき　※実はこれも下に吸収される
	x[i][j] = a[i]

その他のとき
	x[i][j] = max(a[i] - x[i + 1][j], a[n - j - 1] - x[i][j + 1])

------------

上記だと添字が上からになるのでやりづらい。添字をつけ直す


残りがi個で、左からj個とった状態の先手(＝次の人)の得点 x[i][j]

※上のn - i - jがこちらのi、上のiがこちらのj


i == 0 のとき
	x[i][j] = 0

i == 1 のとき
	x[i][j] = a[j]

その他のとき
	x[i][j] = max(a[j] - x[i - 1][j + 1], a[i + j - 1] - x[i - 1][j])

求めるものは
	x[n][0]

------------

オンメモリでできる


*/

void main(){
	int n = read.to!int;
	
	long[] as = readln.chomp.split.map!(to!long).array;
	
	long[] xs;
	foreach(j; 0 .. n + 1) xs ~= 0;
	
	debug writeln("i:0, xs:", xs);
	foreach(i; 1 .. n + 1){
		foreach(j; 0 .. n - i + 1){
			if(j + 1 < n + 1) xs[j] = max(as[j] - xs[j + 1], as[i + j - 1] - xs[j]);
			else xs[j] = as[i + j - 1] - xs[j];
		}
		debug writeln("i:", i, " xs:", xs);
	}
	
	xs[0].writeln;
}

