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 <cstring>
#include <algorithm>
/*
?????????
*/

constexpr int NUM = 300;
int w[NUM] = { 0 };
bool dp[NUM][NUM] = { {false} };
int ddp[NUM+1] = { 0 };

//a~a+1??¨a+2~b?????\??\??\???a~d??¨d+1~r?????\??\??\???a~b-2??¨b-1~b????????????????????¨???????????????
bool isDroped(int a, int b) {
	if (b - a <= 1) return false;
	for (int i = a + 1; i < b; i += 2) {
		if (dp[a][i] && dp[i + 1][b]) return true;
	}
	return false;
}

int main() {
	int n;
	while (std::cin >> n && n) {
		std::memset(dp, 0, sizeof(dp));
		for (int i = 0; i < n; i++) std::cin >> w[i];

		for (int d = 1; d < n; d += 2) { //?????¨?????????
			for (int i = 0; i < n - d; i++) { //?????¨?????´???
				if ((d == 1 || dp[i + 1][i + d - 1]) && std::abs(w[i] - w[i + d]) <= 1){
					dp[i][i + d] = true; //???????????????????????¨????????¨??????
				}
				if (isDroped(i, i + d)) {
					dp[i][i + d] = true;
				}
			}
		}
		std::memset(ddp, 0, sizeof(ddp));
		for (int i = 0; i < n; ++i) {
			ddp[i + 1] = std::max(ddp[i + 1], ddp[i]);
			for (int j = i + 1; j < n; j += 2) {
				if (dp[i][j]) {
					ddp[j + 1] = std::max(ddp[j + 1], ddp[i] + j - i + 1);
				}
			}
		}
		std::cout << ddp[n] << std::endl;
	}
	return 0;
}

C++: #include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <utility>
#include <string>
#include <stack>
#include <regex>

#define REP(i, n) for (int i = 0; i < n; i++)
#define ALL(v) (v).begin(), (v).end()
#define vi vector<int>

using namespace std;

typedef long long ll;

int main()
{
  while (true)
  {
    int n;
    cin >> n;
    int dp[305][305];
    REP(i, 305)
    {
      REP(j, 305)
      {
        dp[i][j] = 0;
      }
    }
    if (n == 0)
    {
      break;
    }
    vi w = vi(n, 0);
    REP(i, n)
    {
      cin >> w[i];
    }
    for (int width = 2; width < n + 1; width++)
    {
      REP(left, n)
      {
        int right = left + width - 1;
        if (right >= n)
        {
          continue;
        }
        // 間のブロックが全部叩けるかつ両端の重さの差が1以下
        if (dp[left + 1][right - 1] == width - 2 && abs(w[left] - w[right]) <= 1)
        {
          dp[left][right] = width;
        }
        for (int k = left; k < right; k++)
        {
          dp[left][right] = max(dp[left][right], dp[left][k] + dp[k + 1][right]);
        }
      }
    }
    cout << dp[0][n - 1] << endl;
  }
  return 0;
}

C++: #include <bits/stdc++.h>
#define rep(i, n) for (int i=0; i<(int)(n); i++)
#define all(v) v.begin(), v.end()
using namespace std;
using ll = long long;
using Graph = vector<vector<int>>;
const ll MOD = 1000000007;
const ll INF = 10000000000000000;
vector<int> x4 = {0, 1, 0, -1}, x8 = {0, 1, 1, 1, 0, -1, -1, -1};
vector<int> y4 = {1, 0, -1, 0}, y8 = {1, 1, 0, -1, -1, -1, 0, 1};
template<class T> struct edge { int from, to; T cost;};
template<class T> inline bool chmin(T& a, T b){if (a>b){a = b; return true;}return false;}
template<class T> inline bool chmax(T& a, T b){if (a<b){a = b; return true;}return false;}
template<class T> inline T powerM(T a,T b){if (b==0) return 1;
T tmp = powerM(a,b/2); if (b%2==0) return tmp*tmp%MOD; else return tmp*tmp%MOD*a%MOD; }
template<class T> inline T power(T a,T b,T m){ if (b==0) return 1;
  T tmp = power(a,b/2,m); if (b%2==0) return tmp*tmp%m; else return tmp*tmp%m*a%m; }
template<class T> inline T gcd(T a, T b){if (b==0) return a; return gcd(b, a%b);}
template<class T> inline T lcm(T a, T b){return a / gcd(a,b) * b;}
// ax+by=gcd(a,b)を解く
template<class T> inline T extgcd(T a,T b,T &x,T &y){if (b==0){x=1; y=0; return a;} T d=extgcd(b,a%b,y,x); y -= a/b*x; return d;}


int N;
vector<int> W;
vector<vector<int>> dp;

void solve(){
  W.assign(N, 0); rep(i, N) cin >>W[i];
  dp.assign(N+1, vector<int>(N+1, -N));
  rep(i, N+1) dp[i][i] = 0;
  rep(i, N) dp[i][i+1] = 0;
  // dp[i][j]...[i,j) のブロックが残っているとき最適な叩き出しを行って取り除けるブロックの個数
  for (int len=2; len<=N; len++){
    for (int i=0; i+len<=N; i++){
      int j = i + len;
      if (dp[i+1][j-1] == len-2){
        if (abs(W[i]-W[j-1]) <= 1) chmax(dp[i][j], len);
        else chmax(dp[i][j], len-2);
      }
      for (int k=i+1; k<j; k++){
        chmax(dp[i][j], dp[i][k] + dp[k][j]);
      }
    }
  }
  cout <<dp[0][N] <<endl;
}

int main() {
  cin >>N;
  while (N > 0){
    solve();
    cin >>N;
  }
}

C++: #include <bits/stdc++.h>
using namespace std;

bool solve(){
	int n;
	cin >> n;
	if(n == 0)return false;
	vector<int> x(n);
	for(int i=0;i<n;i++)
		cin >> x[i];

	vector<vector<int>> dp(n+1,vector<int>(n+1));
	for(int i=0;i<n-1;i++){
		if( abs( x[i] - x[i+1] ) <= 1 )
			dp[i][i+1] = 2;
	}

	for(int d=1;d<n;d++){
		for(int l=0;l<n;l++){
			if( l + d >= n )continue;
			for(int r=l;r<l+d;r++){
				// cout << l << " " << r << " " << r + 1 << " " << l+d << endl;
				dp[l][l+d] = max(dp[l][l+d], dp[l][r] + dp[r+1][l+d]);
			}
			if( l - 1 >= 0 && l + d + 1 < n){
				if( dp[l][l+d] == d + 1 && abs( x[l-1] - x[l+d+1] ) <= 1 ){
					dp[l-1][l+d+1] = max(dp[l-1][l+d+1] ,dp[l][l+d] + 2);
				}
			}
		}
		// cout << endl;
	}
	cout << dp[0][n-1] << endl;
	return true;
}

int main(void){

	while(solve()){}

	return 0;
}