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 <cmath>
#include <iostream>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <utility>
#include <iomanip>

#define int long long int
#define rep(i, n) for(int i = 0; i < (n); ++i)

using namespace std;

typedef pair<int, int> P;

const int INF = 1e15;
const int MOD = 1e9+7;

signed main(){
    while(true){
        int n;
        cin >> n;

        if(n == 0){
            break;
        }

        vector<int> a(n);
        rep(i, n) cin >> a[i];

        vector<vector<bool>> able(n, vector<bool>(n, false));
        rep(i, n-1){
            if(abs(a[i] - a[i+1]) < 2){
                able[i][i+1] = true;
            }
        }
        for(int d = 3; d < n; d += 2){
            rep(i, n){
                if(i + d >= n){
                    continue;
                }

                if(i + 1 < i + d - 1 && able[i+1][i+d-1] && abs(a[i] - a[i+d]) < 2){
                    able[i][i+d] = true;
                    continue;
                }

                for(int k = i+1; k < i + d - 1; k++){
                    if(able[i][k] && able[k+1][i+d]){
                        able[i][i+d] = true;
                        break;
                    }
                }
            }
        }

        vector<vector<int>> dp(n, vector<int>(n));
        rep(i, n){
            rep(j, n){
                if(able[i][j]){
                    dp[i][j] = j - i + 1;
                }
            }
        }

        rep(i, n){
            for(int j = i+1; 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 <bits/stdc++.h>
#define fi first
#define se second
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rrep(i, n) for (int i = 1; i <= (n); ++i)
#define drep(i, n) for (int i = (n)-1; i >= 0; --i)
#define srep(i, s, t) for (int i = s; i < t; ++i)
#define rng(a) a.begin(), a.end()
#define rrng(a) a.rbegin(), a.rend()
#define maxs(x, y) (x = max(x, y))
#define mins(x, y) (x = min(x, y))
#define limit(x, l, r) max(l, min(x, r))
#define lims(x, l, r) (x = max(l, min(x, r)))
#define isin(x, l, r) ((l) <= (x) && (x) < (r))
#define pb push_back
#define eb emplace_back
#define sz(x) (int)(x).size()
#define pcnt __builtin_popcountll
#define uni(x) x.erase(unique(rng(x)), x.end())
#define show(x) cout << #x << " = " << x << endl;
#define PQ(T) priority_queue<T, v(T), greater<T>>
#define bn(x) ((1 << x) - 1)
#define dup(x, y) (((x) + (y)-1) / (y))
#define newline puts("")
#define v(T) vector<T>
#define vv(T) v(v(T))
using namespace std;
typedef long long int ll;
typedef unsigned uint;
typedef unsigned long long ull;
typedef pair<int, int> P;
typedef tuple<int, int, int> T;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<P> vp;
typedef vector<T> vt;


template<typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val){
    std::fill( (T*)array, (T*)(array+N), val );
}


void solve(int n){
  ll dp[400][400];
  Fill(dp,-n);
  vl w(n);
  rep(i,n)cin >> w[i];
  rep(i,n+1){
    dp[i][i] = 0;
    // 半開区間なので、[i][i+1]は積木が1個しか存在しないため、0にする
    if(i<n) dp[i][i+1] = 0;
  }

  for(int bet = 2; bet<=n;bet++){
    for(int i = 0;i+bet<=n;i++){
      int j = i+bet;
      if(dp[i+1][j-1] == j-i-2){
        if(abs(w[i]-w[j-1]) <= 1) maxs(dp[i][j],(ll)(j-i));
        else maxs(dp[i][j],(ll)(j-i-2));
      }
      for(int k = i+1;k<=j-1;k++){
        maxs(dp[i][j],dp[i][k]+dp[k][j]);
      }
    }
  }
  cout<<dp[0][n]<<endl;
}
int main() {
  while(1){
  int n;
  cin >> n;
  if(!n)break;
  else{
    solve(n);
  }
  }
  return 0;
}

C++: 	#include <iostream>
	#include <cstdio>
	#include <algorithm>
	#include <string>
	#include <cstring>
	#include <cctype>
	#include <cmath>
	#include <stack>
	#include <queue>
	#include <vector>
	#include <set>
	#include <map>
	#include <list>
	#include <stdio.h>
	#include <string.h>
	#include <cstdlib>
	#include <math.h>
	#include <bitset>
	#include <iterator>
	#include <iomanip>
	#include <sstream>
	#include <numeric>
	#include <cassert>
	using namespace std;
	int dx[5]={1,0,-1,0,0},dy[5]={0,1,0,-1,0};
	long long gcd(long long a,long long b){if(a%b==0){return b;}else return gcd(b,a%b);}
	long long lcm(long long a,long long b){if(a==0){return b;} return a/gcd(a,b)*b;}
	#define INF 2000000000
	#define MOD 1000000007
	#define sym cout<<"---------"<<endl;
	#define ll long long
	#define mk make_pair
	#define en endl
	#define RE return 0
	#define int ll
	#define P pair<int,int>
	
	int dp[305][305];

signed main(){
	int n;
	while(cin>>n&&n){
		int w[305];
		memset(dp, 0, sizeof(dp));
		for(int i=0; i<n; i++) cin>>w[i];
		
		for(int W=2; W<=n; W++){
			for(int l=0; l<n; l++){
				int r=l+W;
				
				if(dp[l+1][r-1]==W-2&&abs(w[l]-w[r-1])<=1) dp[l][r]=W;
				
				for(int mid=l; mid<=r; mid++){
					dp[l][r]=max(dp[l][r], dp[l][mid]+dp[mid][r]);
				}
			}
		}
		cout<<dp[0][n]<<en;
	}
}

C++: #include <bits/stdc++.h>
#define ll long long
#define pii pair<int, int>
using namespace std;

int dp[500][500];  // 区間[l, r)で取り除くことができるブロック数
int main() {
    int n;
    while (cin >> n, n) {
        vector<int> a(n);
        for (int i = 0; i < n; i++) cin >> a[i];
        memset(dp, 0, sizeof(dp));
        for (int b = 2; b <= n; b++) {
            for (int l = 0; l < n; l++) {
                int r = l + b;
                if (r > n) continue;
                if (dp[l + 1][r - 1] == b - 2 && abs(a[l] - a[r - 1]) <= 1) {
                    dp[l][r] = b;
                }
                for (int m = l; m <= r; m++) {
                    dp[l][r] = max(dp[l][r], dp[l][m] + dp[m][r]);
                }
            }
        }
        cout << dp[0][n] << endl;
    }
    return 0;
}