Go: package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
)

const (
	initialBufSize = 10000000
	maxBufSize     = 100000000
)

var sc *bufio.Scanner

func initScanner(r io.Reader) *bufio.Scanner {
	buf := make([]byte, initialBufSize)

	sc := bufio.NewScanner(r)
	sc.Buffer(buf, maxBufSize)
	sc.Split(bufio.ScanWords) // bufio.ScanLines
	return sc
}

func main() {
	sc = initScanner(os.Stdin)
	resolve()
}

func nextInt(sc *bufio.Scanner) int {
	sc.Scan()
	a, _ := strconv.Atoi(sc.Text())
	return int(a)
}
func nextString(sc *bufio.Scanner) string {
	sc.Scan()
	return sc.Text()
}

func nextIntSlice(sc *bufio.Scanner, n int) (a []int) {
	a = make([]int, n)
	for i := 0; i < n; i++ {
		a[i] = nextInt(sc)
	}
	return a
}

var dp [][]int

func initDP(n int) {
	dp = make([][]int, n+1)
	for i := 0; i < len(dp); i++ {
		dp[i] = make([]int, n+1)
		for j := 0; j < len(dp[0]); j++ {
			dp[i][j] = -1
		}
	}
}

func resolve() {
	ans := []int{}
	for true {
		n := nextInt(sc)
		if n == 0 {
			break
		}
		as := nextIntSlice(sc, n)
		initDP(n)
		_rec(as, n, 0, n)
		ans = append(ans, dp[0][n])
	}
	for _, v := range ans {
		fmt.Println(v)
	}
	return
}

func _rec(as []int, n, l, r int) int {
	if dp[l][r] > -1 {
		return dp[l][r]
	}
	if r-l == 1 { // prevent to hit daruma
		dp[l][r] = 0
		return dp[l][r]
	}
	if r-l == 2 {
		if abs(as[l]-as[r-1]) <= 1 {
			dp[l][r] = 2
		} else {
			dp[l][r] = 0
		}
		return dp[l][r]
	}
	if abs(as[l]-as[r-1]) <= 1 {
		v := _rec(as, n, l+1, r-1)
		// if we can remove internal blocks
		if (r - 1 - (l + 1)) == v {
			dp[l][r] = v + 2
			return dp[l][r]
		} else {
			dp[l][r] = v
		}
	}
	for i := l + 1; i < r; i++ {
		v := _rec(as, n, l, i) + _rec(as, n, i, r)
		if dp[l][r] < v {
			dp[l][r] = v
		}
	}
	return dp[l][r]
}

func abs(v int) int {
	if v < 0 {
		return -v
	}
	return v
}

C++: #include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<sstream>
#include<iomanip>
#include<limits>
#include<deque>
#include<map>
#include<list>
#include<set>
#include <unordered_set>
#include<vector>
#include<cmath>
#include<cstdio>
#include<memory>
#include<bitset>
#include<stack>
#include<functional>
#include<queue>
#include<regex>
#include<time.h>
#include<type_traits>

using namespace std;


#define YES cout<<"YES"<<endl
#define NO cout<<"NO"<<endl
#define Yes cout<<"Yes"<<endl
#define No cout<<"No"<<endl
#define yes cout<<"yes"<<endl
#define no cout<<"no"<<endl

#define Tof(x) (x) ? Yes : No
#define TOF(x) (x) ? YES : NO
#define tof(x) (x) ? yes : no

using ll = long long;

constexpr ll MOD = 1000000007;
constexpr ll INF = 1050000000;
constexpr long long LONGINF = 1005000000000000000;



/*for文でx,yを上下左右確認するやつだよ。正直使いづらいよ。

int dy[] = { 0, 1, 0, -1 };
int dx[] = { 1, 0, -1, 0 };


for (int i = 0; i < 4; i++) {
	int ny = y + dy[i];
	int nx = x + dx[i];
}

*/


/*繰り返し二乗法だよ。modもとってくれるよ。n^kをmodで割った余りでやってくれるよ。

ll POW_MOD(ll n, ll k, ll mod) {
	ll r = 1;

	for (; k > 0; k >>= 1) {
		if (k & 1) {
			r = (r * n) % mod;
		}
		n = (n * n) % mod;
	}
	return r;
}

*/



/*まだ使えないテクニックのメモだよ。

for (int bit = 0; bit < (1<<n); ++bit)//bit全探索用のfor文だよ

*/

class UnionFind {
private:
	std::vector<int> parent;
	std::vector<int> height;
	std::vector<int> m_size;

public:
	UnionFind(int size_) : parent(size_), height(size_, 0), m_size(size_, 1) {
		for (int i = 0; i < size_; ++i) parent[i] = i;
	}
	void init(int size_) {
		parent.resize(size_);
		height.resize(size_, 0);
		m_size.resize(size_, 1);
		for (int i = 0; i < size_; ++i) parent[i] = i;
	}
	int find(int x) {
		if (parent[x] == x) return x;
		return parent[x] = find(parent[x]);
	}
	void unite(int x, int y) {
		x = find(x);
		y = find(y);
		if (x == y) return;
		int t = size(x) + size(y);
		m_size[x] = m_size[y] = t;
		if (height[x] < height[y]) parent[x] = y;
		else parent[y] = x;
		if (height[x] == height[y]) ++height[x];
	}
	bool same(int x, int y) {
		return find(x) == find(y);
	}
	int size(int x) {
		if (parent[x] == x) return m_size[x];
		return size(parent[x] = find(parent[x]));
	}
};

int GCD(int a, int b) {
	while (b) {
		int tmp = a % b;
		a = b;
		b = tmp;
	}
	return a;
}

int main() {
	int dp[310][310];
	bool take[310][310];

	while (1) {
		int n; cin >> n;
		int w[310];
		if (n == 0) { return 0; }
		for (int i = 0; i < n; i++) {
			cin >> w[i];
		}

		memset(take, false,sizeof(take));
		memset(dp, 0, sizeof(dp));

		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n - i; j++) {
				int len = i + 1;
				int s = j;
				int t = j + i;
				for (int k = s; k < t; k++) {
					if (take[s][k] && take[k + 1][t]) { take[s][t] = true; }
				}
				if (len == 2) {
					if (abs(w[s] - w[t]) < 2) { take[s][t] = true; }
				}
				if (take[s][t]) {
					int x = s - 1;
					int y = t + 1;
					while (1) {
						if (x < 0 || x >= n || y < 0 || y >= n) { break; }
						if (abs(w[x] - w[y]) >= 2) { break; }
						take[x][y] = true;
						x--; y++;
					}
				}
			}
		}

		for (int i = 0; i < n; i++) {
			for (int j = i + 1; j < n; j++) {
				if (take[i][j]) { dp[i][j] = j - i + 1; }
			}
		}

		for (int i = 0; i < n; i++) {
			for (int j = i; j < n; j++) {
				for (int k = i; k < j; k++) {
					dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j]);
				}
			}
		}

		cout << dp[0][n - 1] << endl;

	}

	return 0;
}

C++: #include <iostream>
#include <algorithm>
using namespace std;

int N, w[1000];
bool dp[1000][1000];

bool rec(int left, int right) {
    if(dp[left][right]) return true;
    if(left >= right) return false;

    bool ret = false;
    if(!(abs(left - right) % 2)) {
        rec(left + 1, right), rec(left, right - 1);
    } else {
        for(int i = left + 1; i < right; i += 2) {
            ret |= rec(left, i) & rec(i + 1, right);
        }
        ret |= rec(left + 1, right - 1) & (abs(w[left] - w[right]) <= 1);
    }
    return dp[left][right] = ret;
}

int maxi[1001];
int calc(int idx) {

    if(maxi[idx]) return maxi[idx];
    if(idx > N) return 0;

    int ret = 0;
    ret = calc(idx + 1);
    for(int i = idx + 1; i < N; i += 2) {
        if(dp[idx][i]) {
            ret = max(calc(i + 1) + (i - idx + 1), ret);
        }
    }
    return ret;
}

int main() {
    while(cin >> N, N) {
        for(int i = 0; i < N; i++) {
            cin >> w[i];
        }

        fill_n(maxi, 1001, 0);
        fill_n(*dp, 1000*1000, false);
        for(int i = 0; i < N - 1; i++) {
            if(abs(w[i] - w[i + 1]) <= 1) {
                dp[i][i + 1] = true;
            }
        }
        rec(0, N - 1);
        cout << calc(0) << endl;
    }
}