Problem:
Score : 100 points

Problem Statement

Taro and Jiro will play the following game against each other.

Initially, they are given a sequence a = (a_1, a_2, \ldots, a_N).
Until a becomes empty, the two players perform the following operation alternately, starting from Taro:

Remove the element at the beginning or the end of a. The player earns x points, where x is the removed element.

Let X and Y be Taro's and Jiro's total score at the end of the game, respectively.
Taro tries to maximize X - Y, while Jiro tries to minimize X - Y.

Assuming that the two players play optimally, find the resulting value of X - Y.

Constraints

All values in input are integers.

1 \leq N \leq 3000

1 \leq a_i \leq 10^9

Input

Input is given from Standard Input in the following format:

N
a_1 a_2 \ldots a_N

Output

Print the resulting value of X - Y, assuming that the two players play optimally.

Sample Input 1

4
10 80 90 30

Sample Output 1

10

The game proceeds as follows when the two players play optimally (the element being removed is written bold):

Taro: (10, 80, 90, 30) → (10, 80, 90)

Jiro: (10, 80, 90) → (10, 80)

Taro: (10, 80) → (10)

Jiro: (10) → ()

Here, X = 30 + 80 = 110 and Y = 90 + 10 = 100.

Sample Input 2

3
10 100 10

Sample Output 2

-80

The game proceeds, for example, as follows when the two players play optimally:

Taro: (10, 100, 10) → (100, 10)

Jiro: (100, 10) → (10)

Taro: (10) → ()

Here, X = 10 + 10 = 20 and Y = 100.

Sample Input 3

1
10

Sample Output 3

10

Sample Input 4

10
1000000000 1 1000000000 1 1000000000 1 1000000000 1 1000000000 1

Sample Output 4

4999999995

The answer may not fit into a 32-bit integer type.

Sample Input 5

6
4 2 9 7 1 5

Sample Output 5

2

The game proceeds, for example, as follows when the two players play optimally:

Taro: (4, 2, 9, 7, 1, 5) → (4, 2, 9, 7, 1)

Jiro: (4, 2, 9, 7, 1) → (2, 9, 7, 1)

Taro: (2, 9, 7, 1) → (2, 9, 7)

Jiro: (2, 9, 7) → (2, 9)

Taro: (2, 9) → (2)

Jiro: (2) → ()

Here, X = 5 + 1 + 9 = 15 and Y = 4 + 7 + 2 = 13.

Solution in Rust (1.15.1) (judge verdict: Accepted)

// This code is generated by [cargo-atcoder](https://github.com/tanakh/cargo-atcoder)
// Original source code:
/*
#[allow(unused_macros)]
macro_rules! debug {
	($($a:expr),*) => {
		println!(concat!($(stringify!($a), " = {:?}, "),*), $($a),*);
	}
}

#[allow(dead_code)]
const MOD: usize = 1e9 as usize + 7;

use std::cmp::{max, min};

fn rec(l: usize, r: usize, a: &Vec<i64>, dp: &mut Vec<Vec<Option<i64>>>) -> i64 {
	if l == r {
		return a[l];
	}
	if let Some(x) = dp[l][r] {
		return x;
	}
	let mut ret = a[l] - rec(l + 1, r, a, dp);
	ret = max(ret, a[r] - rec(l, r - 1, a, dp));
	dp[l][r] = Some(ret);
	ret
}

fn main() {
	let (r, w) = (std::io::stdin(), std::io::stdout());
	let mut sc = IO::new(r.lock(), w.lock());

	let n: usize = sc.read();
	let a = sc.read_vec::<i64>(n);

	let mut dp = vec![vec![None; n + 1]; n + 1];

	// for i in 1..n + 1 {
	// 	for j in 0..(n - i + 1) {
	// 		let k = i + j;
	// 		if (n - i) % 2 == 0 {
	// 			dp[j][k] = max(dp[j + 1][k] + a[j], dp[j][k - 1] + a[k - 1]);
	// 		} else {
	// 			dp[j][k] = min(dp[j + 1][k] - a[j], dp[j][k - 1] - a[k - 1]);
	// 		}
	// 	}
	// }
	// println!("{}", dp[0][n]);
	println!("{}", rec(0, n - 1, &a, &mut dp));
}

pub struct IO<R, W: std::io::Write>(R, std::io::BufWriter<W>);

impl<R: std::io::Read, W: std::io::Write> IO<R, W> {
	pub fn new(r: R, w: W) -> IO<R, W> {
		IO(r, std::io::BufWriter::new(w))
	}
	pub fn write<S: std::ops::Deref<Target = str>>(&mut self, s: S) {
		use std::io::Write;
		self.1.write(s.as_bytes()).unwrap();
	}
	pub fn read<T: std::str::FromStr>(&mut self) -> T {
		use std::io::Read;
		let buf = self
			.0
			.by_ref()
			.bytes()
			.map(|b| b.unwrap())
			.skip_while(|&b| b == b' ' || b == b'\n' || b == b'\r' || b == b'\t')
			.take_while(|&b| b != b' ' && b != b'\n' && b != b'\r' && b != b'\t')
			.collect::<Vec<_>>();
		unsafe { std::str::from_utf8_unchecked(&buf) }
			.parse()
			.ok()
			.expect("Parse error.")
	}
	pub fn read_vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
		(0..n).map(|_| self.read()).collect()
	}
	pub fn read_chars(&mut self) -> Vec<char> {
		self.read::<String>().chars().collect()
	}
	pub fn read_char_grid(&mut self, n: usize) -> Vec<Vec<char>> {
		(0..n).map(|_| self.read_chars()).collect()
	}
	pub fn read_pairs<T: std::str::FromStr, U: std::str::FromStr>(
		&mut self,
		n: usize,
	) -> Vec<(T, U)> {
		(0..n)
			.map(|_| (self.read::<T>(), self.read::<U>()))
			.collect::<Vec<(T, U)>>()
	}
	pub fn read_matrix<T: std::str::FromStr>(&mut self, n: usize, m: usize) -> Vec<Vec<T>> {
		(0..n)
			.map(|_| (0..m).map(|_| self.read()).collect())
			.collect()
	}
}
*/

fn main() {
    let exe = "/tmp/bin8DAD4827";
    std::io::Write::write_all(&mut std::fs::File::create(exe).unwrap(), &decode(BIN)).unwrap();
    std::fs::set_permissions(exe, std::os::unix::fs::PermissionsExt::from_mode(0o755)).unwrap();
    std::process::exit(std::process::Command::new(exe).status().unwrap().code().unwrap())
}

fn decode(v: &str) -> Vec<u8> {
    let mut ret = vec![];
    let mut buf = 0;
    let mut tbl = vec![64; 256];
    for i in 0..64 { tbl[TBL[i] as usize] = i as u8; }
    for (i, c) in v.bytes().filter_map(|c| { let c = tbl[c as usize]; if c < 64 { Some(c) } else { None } }).enumerate() {
        match i % 4 {
            0 => buf = c << 2,
            1 => { ret.push(buf | c >> 4); buf = c << 4; }
            2 => { ret.push(buf | c >> 2); buf = c << 6; }
            3 => ret.push(buf | c),
            _ => unreachable!(),
        }
    }
    ret
}

const TBL: &'static [u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const BIN: &'static str = "<base64-encoded ELF executable removed>";