Problem:
Daruma Otoshi

You are playing a variant of a game called "Daruma Otoshi (Dharma Block Striking)".

At the start of a game, several wooden blocks of the same size but with varying weights
are stacked on top of each other, forming a tower.
Another block symbolizing Dharma is placed atop.
You have a wooden hammer with its head thicker than the height of a block,
but not twice that.

You can choose any two adjacent blocks, except Dharma on the top,
differing at most 1 in their weight,
and push both of them out of the stack with a single blow of your hammer.
The blocks above the removed ones then fall straight down,
without collapsing the tower.

You cannot hit a block pair with weight difference of 2 or more,
for that makes too hard to push out blocks while keeping the balance of the tower.
There is no chance in hitting three blocks out at a time,
for that would require superhuman accuracy.

The goal of the game is to remove as many blocks as you can.
Your task is to decide the number of blocks that can be removed
by repeating the blows in an optimal order.

Figure D1. Striking out two blocks at a time

In the above figure, with a stack of four blocks weighing 1, 2, 3, and
1, in this order from the bottom, you can hit middle
two blocks, weighing 2 and 3, out from the stack. The blocks above will
then fall down, and two blocks weighing 1 and the Dharma block will remain.
You can then push out the remaining pair of weight-1 blocks after that.

Input

The input consists of multiple datasets.
The number of datasets is at most 50.
Each dataset is in the following format.

n

w1 w2 … wn

n is the number of blocks, except Dharma on the top.
n is a positive integer not exceeding 300.
wi gives the weight of the i-th block counted from the bottom.
wi is an integer between 1 and 1000, inclusive.

The end of the input is indicated by a line containing a zero.

Output

For each dataset, output in a line the maximum number of blocks you can remove.

Sample Input

4
1 2 3 4
4
1 2 3 1
5
5 1 2 3 6
14
8 7 1 4 3 5 4 1 6 8 10 4 6 5
5
1 3 5 1 3
0

Output for the Sample Input

4
4
2
12
0

Solution in JAVA (judge verdict: Accepted)

public class Main {

	private int[] d;
	private int n;
	
	private Pair[] scan() {
		java.util.Set<Pair> lis = new java.util.TreeSet<Pair>();
		
		for (int p = 0; p + 1 < n; ++p) {
			if (Math.abs(d[p + 1] - d[p]) <= 1)
				lis.add(new Pair(p, p + 1));
		}
		for (int l = 4; l <= n; l += 2) {
			for (int s = 0; s + l <= n; ++s) {
				final int e = s + l - 1;
				if (lis.contains(new Pair(s + 1, e - 1)) && Math.abs(d[e] - d[s]) <= 1) {
					lis.add(new Pair(s, e));
					continue ;
				}
				for (int j = s + 1; j + 1 < e; j += 2) {
					if (lis.contains(new Pair(s, j)) && lis.contains(new Pair(j + 1, e))) {
						lis.add(new Pair(s, e));
						break ;
					}
				}
			}
		}
		
		return lis.toArray(new Pair[lis.size()]);
	}
	
	public void run(java.io.InputStream in, java.io.PrintStream out) {
		try (java.util.Scanner sc = new java.util.Scanner(in)) {
			for (;;) {
				n = sc.nextInt();
				if (n == 0) break ;
				d = new int[n];
				for (int i = 0; i < n; ++i)
					d[i] = sc.nextInt();
				
				Pair[] seq = scan();
				java.util.Arrays.sort(seq);
				
				int[] fullSize = new int[n + 1];
				for (int i = 0; i < seq.length; ++i) {
					final Pair p = seq[i];
					final int score = (p.u - 1 < 0 ? 0 : fullSize[p.u - 1]) + p.length;
					for (int j = p.v; j <= n; ++j) {
						if (score <= fullSize[j]) break ;
						fullSize[j] = score;
					}
				}
				out.println(fullSize[n]);
			}
		}
	}
	
	public static void main(String[] args) {
		(new Main()).run(System.in, System.out);
	}

	private static class Pair implements Comparable<Pair> {
		public final int u;
		public final int v;
		public final int length;
		
		public Pair(int u, int v) {
			this.u = Math.min(u, v);
			this.v = Math.max(u, v);
			this.length = v - u + 1;
		}
		
		@Override
		public int compareTo(Pair o) {
			if (this.u < o.u) return -1;
			if (o.u < this.u) return 1;
			if (this.v < o.v) return -1;
			if (o.v < this.v) return 1;
			return 0;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + u;
			result = prime * result + v;
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Pair other = (Pair) obj;
			if (u != other.u)
				return false;
			if (v != other.v)
				return false;
			return true;
		}
		
		@Override
		public String toString() {
			return "(" + this.u + ", " + this.v + ")";
		}
	}
	
}