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 <bits/stdc++.h>
using namespace std;
using ll = long long; using ull = unsigned long long;
//#define int ll
using vb = vector<bool>; using vvb = vector<vb>;
using vi = vector<int>; using vvi = vector<vi>;
using vl = vector<ll>; using vvl = vector<vl>;
template<class T> using V = vector<T>;
template<class T> using VV = vector<V<T>>;
#define fi first
#define se second
#define maxs(x,y) (x=max(x,y))
#define mins(x,y) (x=min(x,y))
using pii = pair<int,int>; using pll = pair<ll,ll>;
#define FOR(i,a,b) for(ll i = (a); i < (ll)(b); ++i)
#define REP(i,n) FOR(i,0,n)
#define RFOR(i,a,b) for(ll i = (ll)(b)-1;i >= a;--i)
#define RREP(i,n) RFOR(i,0,n)
#define ALL(obj) (obj).begin(), (obj).end()
#define rALL(obj) (obj).rbegin(), (obj).rend()
#define eb(val) emplace_back(val)
const double PI = acos(-1), EPS = 1e-10;
const ll MOD = 1e9+7;
template<class T> istream& operator>>(istream &is,vector<T> &st){
  for(size_t i=0;i<st.size();++i) is >> st[i];
  return is;
}
template<class T> istream& operator>>(istream &is,vector<vector<T>> &st){
  for(size_t i=0;i<st.size();++i) is >> st[i];
  return is;
}
template<class T> ostream& operator<<(ostream &os, const vector<T> &st){
  for(size_t i=0;i<st.size();++i){
    if(i==st.size()-1) os << st[i];
    else os << st[i] << " ";
  }
  return os;
}
template<class T> ostream& operator<<(ostream &os, const vector<vector<T>> &st){
  for(size_t i=0;i<st.size();++i){
    os << st[i];
    if(i!=st.size()-1) os << endl;
  }
  return os;
}
int N;
vvi dp;
vi w;
int solve(){
  for(int W = 2; W <= N; W++){ //区間の大きさ
  for(int l = 0; l < N; l++){
    int r = l + W;
    if(r > N) continue;
    if(dp[l+1][r-1]==W-2 && abs(w[l]-w[r-1]) <= 1) dp[l][r] = W; //遷移1
    for(int m = l+1; m < r;m++) //遷移2
    dp[l][r] = max(dp[l][r],dp[l][m]+dp[m][r]);
  }
}
return dp[0][N];
}
signed main(){
  cin.tie(0);
  ios::sync_with_stdio(false);
  while(cin >> N,N){
    dp.assign(N+1,vi(N+1,0));
    w.resize(N);
    cin >> w;
    cout << solve() << endl;
  }
}

C++: #include <bits/stdc++.h>
#include <math.h>

using namespace std;

template<typename T>
long long modpow(const T n,const T p,const T mod);
template<typename T>
long long modinv(const T n,const T mod);
template<typename T>
bool chmax(T &a,const T &b);
template<typename T>
bool chmin(T &a,const T &b);

long long inf=1000000007;
long long n;
vector<long long> v;
vector<vector<long long>> dp;

long long solve(long long l,long long r){
	if(r-l<=1) return 0;
	if(r-l==2){
		if(abs(v.at(l)-v.at(l+1))<=1) return 2;
		else return 0;
	}

	long long &ret=dp.at(l).at(r);
	if(ret!=-1) return ret;

	if(abs(v.at(l)-v.at(r-1))<=1 && solve(l+1,r-1)==r-l-2) chmax(ret,r-l);
	else{
		for(long long i=l+1;i<=r-1;i++){
			chmax(ret,solve(l,i)+solve(i,r));
		}
	}

	return ret;
}

int main(){
	cin>>n;
	while(n!=0){
		v.resize(n);
		for(long long i=0;i<n;i++) cin>>v.at(i);
		dp.assign(n+1,vector<long long>(n+1,-1));

		cout<<solve(0,n)<<endl;

		cin>>n;
	}

	return 0;
}

template<typename T>
long long modpow(const T n,const T p,const T mod){
	if(p==0) return 1;
	if(p%2==0){
		long long a=modpow(n,p/2,mod);
		return a*a%mod;
	}
	if(p%2==1) return (modpow(n,p-1,mod)*n)%mod;
	cerr<<"ERROR"<<endl;
	return 1;
}

template<typename T>
long long modinv(const T n,const T mod){
	return modpow(n,mod-2,mod);
}

template<typename T>
bool chmax(T &a,const T &b){
	if(a<b){
		a=b;
		return 1;
	}
	return 0;
}

template<typename T>
bool chmin(T &a,const T &b){
	if(a>b){
		a=b;
		return 1;
	}
	return 0;
}

C++: #include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<math.h>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;

#define MAX 300
int n;
int w[MAX];
map<string, int> wmap;

string nToStr(int n) {
	string tmp = "";
	for (int i = 0; i < n; i++) {
		tmp += "1";
	}
	return tmp;
}

int next(string s, int now) {
	for (int i = now+1; i < n; i++) {
		if (s[i] == '1') return i;
	}
	return n;
}

string pop(string s,int a,int b) { //w???a????????¨b?????????????????????
	s[a] = '0';
	s[b] = '0';
	return s;
}

int daruma(string s) {
	if (wmap.find(s) != wmap.end()) return wmap[s];
	

	int max = 0;
	for (int i = 0; i < n - 1; i++) {
		if (s[i] == '1') {
			if (s[next(s, i)] != n && abs(w[i] - w[next(s, i)]) <= 1) {
				int tmp = daruma(pop(s, i, next(s, i))) + 2;
				if (tmp > max) max = tmp;
			}
		}
	}

	wmap.insert(map<string, int>::value_type(s, max));
	return max;
}

int main() {
	cin >> n;
	while (n) {
		wmap.clear();
		for (int i = 0; i < n; i++) {
			cin >> w[i];
		}

		cout << daruma(nToStr(n)) << endl;

		cin >> n;
	}
	return 0;
}

C++: #include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); i++)
#define rep1(i, n) for (int i = 1; i < (n); i++)
#define all(v) (v).begin(), (v).end()
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
using namespace std;
typedef long long LL;
const int INF = 999999999;

int dp[334][334];
int w[334];

int rec(int l, int r){
    assert(l < r);
    if(dp[l][r] >= 0) return dp[l][r];
    if(r-l == 1) return dp[l][r] = 0;
    int rm = (abs(w[r-1]-w[l]) <= 1 ? 2 : 0);
    if(r-l == 2) return dp[l][r] = rm;
    int ret = rec(l+1, r-1);
    if(ret == r-l-2) ret += rm;
    for(int mid=l+1; mid<r; mid++) {
        ret = max(ret, rec(l, mid)+rec(mid, r));
    }
    return dp[l][r] = ret;
}

int main(){
    int n;
    cin >> n;
    while(n > 0){
        memset(dp, -1, sizeof(dp));
        rep(i, n) cin >> w[i];
        cout << rec(0, n) << endl;

        // rep(i, n+1){
        //     rep(j, n+1) cout << dp[i][j] << " ";
        //     cout << endl;
        // }
        cin >> n;
    }
}