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
w
1
w
2
…
w
n
n
is the number of blocks, except Dharma on the top.
n
is a positive integer not exceeding 300.
w
i
gives the weight of the
i
-th block counted from the bottom.
w
i
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

Submitted solutions:

code_snippet: #include <iostream>
#include <vector>

using namespace std;


int main(){

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

        vector<vector<int>> dp(n+1, vector<int>(n+1, 0));
        for(int width=2; width<=n; width++){
            for (int l=0; l+width<=n; l++){
                int r = l + width;
                // if (r >= n) continue;
                // dp[l+1][r-1] == r - l - 2 : 間の全てのブロックを落とせる。
                // cout << "r=" << r << ", l=" << l << endl;
                if (dp[l+1][r-1] == r - l - 2 && abs(w[r-1]-w[l]) <= 1){
                    dp[l][r] = width;
                    // cout << "all" << endl;
                }
                else{
                    for (int mid=l; mid<=r; mid++){
                        // cout << "mid=" << mid << ", dp[l][mid]=" << dp[l][mid] << ", dp[mid][r]=" << dp[mid][r] << endl;
                        dp[l][r] = max(dp[l][r], dp[l][mid] + dp[mid][r]);
                    }
                }
                // cout << "dp[" << l << "][" << r << "] = " << dp[l][r] << endl;
            }
        }
        cout << dp[0][n] << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 3768
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
using  ll=long long;
#define rep(a,b,c) for(int a=b;a<c;a++)
#define rep1(a,b,c) for(int a=b;a>=c;a--)
#define vc vector
#define pbk push_back
#define ebk emplace_back
#define fst first
#define snd second
#define sz(a) (int)a.size()
#define out(a,b,c,d,e) cout << a << " " << b << " " << c << " " << d << " " << e << endl
using  pii=pair<int,int>;

void chmax(int &a,int b){a=max(a,b);return;}
void chmin(int &a,int b){a=min(a,b);return;}

signed main() {
	int n;
	vc<int> ans;
	while(true){
		cin >> n;
		if(n==0) break;
		vc<int> a(n);
		rep(i,0,n) cin >> a[i];


		vc dp(n+1,vc<int>(n+2,-1));


		auto dfs=[&](auto dfs,int s,int t)->int{
			if(dp[s][t]!=-1) return dp[s][t];
			if(t-s<=1) return 0;
			if(t-s==2){
				if(abs(a[s]-a[s+1])<=1) return dp[s][t]=2;
				else return dp[s][t]=0;
			}
			int tmp=0;
			if(abs(a[s]-a[t-1])<=1 && dfs(dfs,s+1,t-1)==t-s-2){
				chmax(tmp,t-s);
			}
			rep(i,s+1,t){
				int r=dfs(dfs,s,i)+dfs(dfs,i,t);
				chmax(tmp,r);
			}
			return dp[s][t]=tmp;
		};

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

	}
	//for(int x:ans) cout << x << endl;
	return 0;
}
accuracy: 1
time_ms: 840
memory_kb: 3968
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;
using  ll=long long;
#define rep(a,b,c) for(int a=b;a<c;a++)
#define rep1(a,b,c) for(int a=b;a>=c;a--)
#define vc vector
#define pbk push_back
#define ebk emplace_back
#define fst first
#define snd second
#define sz(a) (int)a.size()
#define out(a,b,c,d,e) cout << a << " " << b << " " << c << " " << d << " " << e << endl
using  pii=pair<int,int>;

void chmax(int &a,int b){a=max(a,b);return;}
void chmin(int &a,int b){a=min(a,b);return;}

signed main() {
	int n;
	vc<int> ans;
	while(true){
		cin >> n;
		if(n==0) break;
		vc<int> a(n);
		rep(i,0,n) cin >> a[i];


		vc dp(n+1,vc<int>(n+2,-1));


		auto dfs=[&](auto dfs,int s,int t)->int{
			if(dp[s][t]!=-1) return dp[s][t];
			if(t-s<=1) return 0;
			if(t-s==2){
				if(abs(a[s]-a[s+1])<=1) return 2;
				else return 0;
			}
			int tmp=0;
			if(abs(a[s]-a[t-1])<=1 && dfs(dfs,s+1,t-1)==t-s-2){
				chmax(tmp,t-s);
			}
			rep(i,s+1,t){
				int r=dfs(dfs,s,i)+dfs(dfs,i,t);
				chmax(tmp,r);
			}
			dp[s][t]=tmp;
			return tmp;
		};

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

	}
	//for(int x:ans) cout << x << endl;
	return 0;
}
accuracy: 1
time_ms: 870
memory_kb: 3968
final_rank: 20

code_snippet: #include <bits/stdc++.h>
#define ALL(obj) begin(obj), end(obj)
using namespace std;

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

int N;
vector<int> w;
vector<vector<int>> dp;

int rec(int l = 0, int r = N) { // メモ化再帰
    if ((r - l) <= 1) return 0;
    if ((r - l) == 2) {
        if (abs(w[l] - w[l + 1]) <= 1) {  // 隣り合う2つの差が1以下
            return 2;
        } else {
            return 0;
        }
    }

    int &ret = dp[l][r]; // 更新の対象についての参照を宣言
    if (ret != -1) return ret;  // 既に計算済みならその値を使う

    // 1. 全部取り除けるとき
    if (abs(w[l] - w[r-1]) <= 1 && rec(l + 1, r - 1) == r - l - 2) chmax(ret, r - l);
    // 2. そうでない時
    for (int i = l + 1; i <= r - 1; i++) {
        chmax(ret, rec(l, i) + rec(i, r));
    }

    return ret;
}

int main() {
    vector<int> ans;
    while (true) {
        cin >> N;
        if (N == 0) break;
        w.resize(N);
        for (int i = 0; i < N; i++) {
            cin >> w.at(i);
        }

        dp.assign(N + 2, vector<int>(N + 2, -1));  // 初期化

        ans.push_back(rec());
    }

    for (auto i : ans) {
        cout << i << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 700
memory_kb: 3816
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair < int, int > ;
using pll = pair < ll, ll > ;
#define all(x) x.begin(), x.end()
const double pi = 3.141592653589793238;
const string ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string abc = "abcdefghijklmnopqrstuvwxyz";
//n以下の約数列挙。O(√n)
vector<ll> enumdiv(ll n){
    vector<ll> res;
    for(ll i = 1; i*i <= n; i++){
        if(n%i==0){
            res.push_back(i);
            if(i*i!=n) res.push_back(n/i); 
        }
    }
    sort(all(res));
    return res;
}
//nを素因数分解する。{素数、指数}
vector<pair<ll,ll>> prime_factorize(ll n){
    vector<pair<ll,ll>> res;
    for(ll a = 2; a*a<=n; a++){
        if(n%a==0){
            ll ex = 0;//指数部分
            while(n%a==0){
                n/=a;
                ex++;
            }
            res.push_back({a,ex});
        }
    }
    if(n!=1) res.push_back({n,1});
    return res;
}
struct UnionFind{
    vector<int> par;//各要素の親 root=-1
    UnionFind(int sz){
        par.assign(sz,-1);
    }
    bool unite(int x,int y){
        x = find(x);
        y = find(y);
        if(x==y) return false;
        if(par[x]>par[y]) swap(x,y);
        par[x] += par[y];
        par[y] = x;
        return true;
    }
    int find(int k){//kが属する根ノードを返す
        if(par[k]<0) return k;
        return par[k] = find(par[k]);
    }
    int size(int k){//kが属する木のサイズ
        return -par[find(k)];
    }
    vector<vector<int>> groups(){//全ての要素を連結成分ごとにグループ分けして返す。
        vector<vector<int>> result;
        map<int,vector<int>> mp;
        for(int i = 0; i < (int)par.size(); i++){
            mp[find(i)].push_back(i);
        }
        for(auto [key,val] : mp){
            result.push_back(val);
        }
        return result;
    }
};
// a^n mod を計算する
long long modpow(long long a, long long n, long long mod) {
	long long res = 1;
	while (n > 0) {
		if (n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res;
}
int main() {
    int n;
    while(cin >> n){
        if(n==0) break;
        vector<int> w(n);
        for(int i = 0; i < n; i++){
            cin >> w[i];
        }
        vector<vector<int>> dp(n+1,vector<int>(n+1,-1));
        auto rec = [&](auto self,int l,int r) -> int{
            if(r-l<=1) return 0;
            if(r-l==2){
                if(abs(w[l+1]-w[l])<=1){
                    return 2;
                }else return 0;
            }
            if(dp[l][r]!=-1) return dp[l][r];
            if(abs(w[l]-w[r-1])<=1&&self(self,l+1,r-1)==r-l-2){//全部取り除ける時
                dp[l][r] = max(dp[l][r],r-l);
            }
            for(int i = l+1; i <= r-1; i++){
                dp[l][r] = max(dp[l][r],self(self,l,i)+self(self,i,r));
            }
            return dp[l][r];
        };
        cout << rec(rec,0,n) << endl;
    }
}
accuracy: 1
time_ms: 1100
memory_kb: 3748
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
#if __has_include(<atcoder/all>)
#include <atcoder/math>
using namespace atcoder;
#endif

using ll = long long;
using ld = long double;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vvvi = vector<vector<vector<int>>>;
using vll = vector<ll>;
using vvll = vector<vector<ll>>;
using vvvll = vector<vector<vector<ll>>>;
using vd = vector<double>;
using vvd = vector<vector<double>>;
using vstr = vector<string>;
using vchar = vector<char>;
using vvchar = vector<vector<char>>;
using vb = vector<bool>;
using vvb = vector<vector<bool>>;
using pii = pair<int,int>;
using pll = pair<long long, long long>;
using Graph = vector<vector<int>>;
const int dx[8] = {1, 0, -1, 0, 1, 1, -1, -1};
const int dy[8] = {0, 1, 0, -1, 1, -1, 1, -1};

#define rep(i, a, b) for(int i = (int)a; i < (int)b; i++)
#define REP(i, a, b) for (int i = (int)a; i <= (int)b; i++)
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#define YESNO(flag) cout << (flag ? "Yes" : "No") << "\n"
#define spa " "

const int inf = 1070000000;
const long long INF = 4500000000000000000;
const long long MOD = 998244353;
//const long long MOD = 1000000007;
const double pi = 3.141592653589793238;
const double eps = (1e-10);
const string ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string abc = "abcdefghijklmnopqrstuvwxyz";

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;
}

//xのn乗
ll llpow(ll x, ll n) {
    ll ans = 1;
    while(n > 0) {
        if(n & 1) ans *= x;
        x *= x;
        n >>= 1; 
    }
    return ans;
}
ll modpow(ll x, ll n, ll mod) {
    ll ans = 1;
    while(n > 0) {
        if(n & 1) ans = ans * x % mod;
        x = x * x % mod;
        n >>= 1;
    }
    return ans;
}
//mod pでのaの逆元
ll inverse(ll a, ll p) {
    return modpow(a, p-2, p);
}
//nの階乗
ll fact(ll n) {
    if(n == 0) return 1;
    else return n * fact(n-1);
}
ll modfact(ll n, ll mod) {
    if(n == 0) return 1;
    else return (n * modfact(n-1, mod)) % mod;
}
//nCr=n!/r!(n-r)! mod p
ll comb(ll n, ll r, ll mod) {
    ll a = modfact(n, mod), b = modfact(r, mod), c = modfact(n-r, mod);
    b = inverse(b, mod); c = inverse(c, mod);
    return (((a*b)%mod)*c)%mod;
}

//1+2+...+n = n(n+1)/2
ll triangle(ll n) {
    ll x = n*(n+1);
    return x/2;
}
//素数判定
bool is_prime(long long x) {
    if(x == 1) return false;
    
    for(long long i = 2; i*i <= x; i++) {
        if(x % i == 0) return false;
    }
    return true;
}

//座標圧縮
vector<int> compress(vector<int> A) {
    vector<int> B = A;

    sort(B.begin(), B.end());
    B.erase(unique(B.begin(), B.end()), B.end());

    vector<int> res(A.size());
    for(int i = 0; i < (int)A.size(); i++) {
        res[i] = lower_bound(B.begin(), B.end(), A[i]) - B.begin();
    }
    return res;
}

//正方形グリッドの右回転
void rotate_right(vector<vector<char>> &S) {
    int N = S.size();
    auto T = S;
    rep(i,0,N) rep(j,0,N) {
        T[i][j] = S[N-1-j][i];
    }
    S = T;
}
//左回転
void rotate_left(vector<vector<char>> &S) {
    int N = S.size();
    auto T = S;
    rep(i,0,N) rep(j,0,N) {
        T[i][j] = S[j][N-1-i];
    }
    S = T;
}

//2点(a,b)と(x,y)の距離
double dist2(ll a, ll b, ll x, ll y) {
    return sqrt((a-x)*(a-x) + (b-y)*(b-y));
}
int man(int a, int b, int x, int y) {
    return abs(a-x) + abs(b-y);
}

//桁数
int digit(ll N) {
    if(N <= 9) return 1;

    return 1 + digit(N / 10);
}
//A進数文字列NをB進数に変換. A,Bは10以下
string base_change(string N, ll A, ll B) {
    ll X = stoll(N), Y = 0;

    ll i = 1;
    while(X != 0) {
        Y += (X % 10) * i;
        i *= A;
        X /= 10;
    }

    X = Y, Y = 0;
    i = 1;
    while(X != 0) {
        Y += (X % B) * i;
        i *= 10;
        X /= B;
    }

    return to_string(Y);
}
//回文判定
bool palin(string S) {
    rep(i,0,S.size()) {
        if(S[i] != S[S.size()-1-i]) return false;
    }
    return true;
}

//hh:mm:ss to second
int convert_to_time(string S) {
    ll h = 10*(S[0]-'0') + (S[1]-'0');
    ll m = 10*(S[3]-'0') + (S[4]-'0');
    ll s = 10*(S[6]-'0') + (S[7]-'0');
    
    return h*3600+m*60+s;
}

//DFS
void dfs(const Graph &G, int v, vector<bool> &seen) { 
    seen[v] = true;
    
    for (auto next_v : G[v]) { 
        if (!seen[next_v]) {
            dfs(G, next_v, seen);
        }
    }
}
void griddfs(const vector<vector<char>> &G, int x, int y, vector<vector<bool>> &seen) {
    int H = G.size(), W = G[0].size();
    seen[x][y] = true;
    
    for (int i = 0; i < 8; i++) { 
        int nx = x + dx[i], ny = y + dy[i];
        if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
        if (!seen[nx][ny] and G[nx][ny] != '#') griddfs(G, nx, ny, seen);
    }
}
//BFS
void bfs(const Graph &G, int v, vector<int> &dist) {
    rep(i,0,dist.size()) dist[i] = inf;
    dist[v] = 0;
    queue<int> q;
    q.push(v);
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        for(auto next_u : G[u]) {
            if(dist[next_u] == inf) {
                dist[next_u] = dist[u] + 1;
                q.push(next_u);
            }
        }
    }
}
void gridbfs(const vector<vector<char>> &G, int x, int y, vector<vector<int>> &dist) {
    int H = G.size(), W = G[0].size();
    rep(i,0,H) rep(j,0,W) dist[i][j] = inf;
    dist[x][y] = 0;
    queue<pair<int, int>> q;
    q.push(make_pair(x, y));
    while(!q.empty()) {
        int x = q.front().first, y = q.front().second;
        q.pop();
        for(int i = 0; i < 4; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
            if(dist[nx][ny] == inf and G[nx][ny] != '#') {
                dist[nx][ny] = dist[x][y] + 1;
                q.push(make_pair(nx, ny));
            }
        }
    }
}
//ワーシャル・フロイド
vector<vector<ll>> floyd(vector<vector<ll>> G) {
    int N = G.size();
    auto dp = G;
    for (int k = 0; k < N; k++){
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if(dp[i][j] > dp[i][k] + dp[k][j] and dp[i][k] != INF and dp[k][j] != INF) {
                    dp[i][j] = dp[i][k] + dp[k][j];
                }
            }
        }
    }
    return dp;
}

//Union-Find
struct UnionFind {
    vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2
    
    UnionFind(int N) : par(N) { //最初は全てが根であるとして初期化
        for(int i = 0; i < N; i++) par[i] = i;
    }
    
    int root(int x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
        if (par[x] == x) return x;
        return par[x] = root(par[x]);
    }
    
    void unite(int x, int y) { // xとyの木を併合
        int rx = root(x); //xの根をrx
        int ry = root(y); //yの根をry
        if (rx == ry) return; //xとyの根が同じ(=同じ木にある)時はそのまま
        par[rx] = ry; //xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
    }
    
    bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
        int rx = root(x);
        int ry = root(y);
        return rx == ry;
    }
};

void solve() {
}

int main() {
    while(1) {
        int N; cin >> N;
        if(N == 0) break;
        vi A(N); rep(i,0,N) cin >> A[i];
        vvi dp(N+1, vi(N+1, 0));
        REP(k,2,N) {
            REP(l,0,N-k) {
                int r = l+k;
                rep(i,l+1,r) chmax(dp[l][r], dp[l][i]+dp[i][r]);
                if(abs(A[l]-A[r-1]) <= 1 and dp[l+1][r-1] == r-l-2) dp[l][r] = r-l;
            }
        }
        cout << dp[0][N] << "\n";
    }

    return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 3768
final_rank: 7

code_snippet: // #pragma GCC optimize("Ofast")
// #pragma GCC optimize ("unroll-loops")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

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

#include<complex>
//#include <ext/pb_ds/tree_policy.hpp>
//#include <ext/pb_ds/assoc_container.hpp>

#define x() real()
#define y() imag()
#define endl '\n'
#define ll long long
typedef long double T;
typedef complex<T> point;
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define fastIO cin.tie(0)->sync_with_stdio(0);

//using namespace __gnu_pbds;
//template <typename T> using o_set = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;

//If you can't solve a problem then there's an easier
//sub-problem that you can not solve.Find it!!

const int N = 310;
int a[N] , can[N][N] , dp[N][N];

int main()
{
    fastIO;

    //int t = 1; cin >> t;

    while (1)
    {
        int n; cin >> n;
        if (n == 0) break;

        memset(can , 0 , sizeof can);
        memset(dp , 0 , sizeof dp);

        for (int i = 1 ; i <= n ; i++) cin >> a[i];

        for (int len = 2 ; len <= n ; len += 2)
        {
            for (int i = 1 ; i + len - 1 <= n ; i++)
            {
               int lim = i + len - 1;

               for (int j = i + 1 ; j <= lim ; j++)
               {
                   if (abs(a[i] - a[j]) > 1) continue;

                   bool left = (j == i + 1) || can[i + 1][j - 1];
                   bool right = (j + 1 > lim) || can[j + 1][lim];

                   if (left && right)
                    can[i][lim] |= 1;
               }
            }
        }

        int ans = 0;

        for (int len = 2 ; len <= n ; len++)
        {
             for (int i = 1 ; i  + len - 1 <= n ; i++)
             {
                 int j = i + len - 1;

                 if (can[i][j])
                 {
                     dp[i][j] = j - i + 1;
                     ans = max(ans , dp[i][j]);
                     continue;
                 }

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

                 ans = max(ans , dp[i][j]);
             }
        }

        cout << ans << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 4120
final_rank: 13

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

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    while (true) {
        int n;
        if (!(cin >> n)) break;
        if (n == 0) break;

        vector<int> w(n);
        for (int i = 0; i < n; i++) cin >> w[i];

        vector<vector<bool>> can(n, vector<bool>(n, false));
        vector<vector<int>> dp(n, vector<int>(n, 0));

        for (int len = 2; len <= n; len++) {
            for (int l = 0; l + len - 1 < n; l++) {
                int r = l + len - 1;

                if (len % 2 == 0) {
                    for (int m = l + 1; m <= r; m++) {
                        if (abs(w[l] - w[m]) <= 1) {
                            bool left_ok = (m == l + 1) || can[l + 1][m - 1];
                            bool right_ok = (m == r) || can[m + 1][r];
                            if (left_ok && right_ok) {
                                can[l][r] = true;
                                break;
                            }
                        }
                    }
                }

                int best = can[l][r] ? len : 0;
                for (int k = l; k < r; k++) {
                    best = max(best, dp[l][k] + dp[k + 1][r]);
                }
                dp[l][r] = best;
            }
        }

        cout << dp[0][n - 1] << "\n";
    }

    return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 3532
final_rank: 3

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

int main() {
    int n;
    while(cin >> n){
        if(n==0){
            return 0;
        }

        vector<int> w(n);
        for(int i=0; i<n; i++){
            cin >> w[i];
        }

        vector<vector<int>> dp(n, vector<int>(n,0));
        for(int leng=2; leng<=n; leng++){
            for(int i=0; i<n-leng+1; i++){
                int j=i+leng-1;
                
                if(dp[i+1][j-1]==j-i-1 && abs(w[i]-w[j])<=1){
                    dp[i][j]=j-i+1;
                    continue;
                }
    
                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] << '\n';

    }
}
accuracy: 1
time_ms: 110
memory_kb: 3792
final_rank: 5

code_snippet: #include <bits/stdc++.h>

using namespace std;

int main() {
  vector<int> res_list;
  while (true) {
    int n; cin >> n;
    if (n == 0) break;
    vector<int> W(n);
    for (int i = 0; i < n; ++i) cin >> W[i];

    vector<vector<int>> dp(n, vector<int>(n,INT_MAX));
    for (int i = 0; i < n; ++i) dp[i][i] = 1;
    for (int l = 2; l <= n; ++l) {
      for (int i = 0; i < n - l + 1; ++i) {
        int j = i + l - 1;
        if (l == 2) {
          if (abs(W[i] - W[j]) <= 1) dp[i][j] = 0;
          else  dp[i][j] = 2;
          continue;
        }
        if (abs(W[i] - W[j]) <= 1 && dp[i + 1][j - 1] == 0) {
          dp[i][j] = 0;
          continue;
        }
        for (int k = i; k < j; ++k) {
          dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j]);
        } 
      }
    }

    res_list.push_back(n - dp[0][n-1]);
  }
  for (int res: res_list) cout << res << endl;
  return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 3468
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
using  ll=long long;
using  pii=pair<int,int>;
#define rep(a,b,c) for(int a=b;a<c;a++)
#define rep1(a,b,c) for(int a=b;a>=c;a--)
#define vc vector
#define pbk push_back
#define ebk emplace_back
#define fst first
#define snd second
#define sz(a) (int)a.size()
#define out(a,b,c,d,e) cout << a << " " << b << " " << c << " " << d << " " << e << endl

void chmax(int &a,int b){a=max(a,b);return;}

signed main() {
	int n;
	while(true){
		cin >> n;
		if(n==0) return 0;
		vc<int> w(n);
		rep(i,0,n) cin >> w[i];

		vc dp(n,vc<int>(n+1,-1));

		auto dfs=[&](auto dfs,int s,int t)->int{
			if(dp[s][t]!=-1) return dp[s][t];
			if(t-s==1) return dp[s][t]=0;
			if(t-s==2){
				if(abs(w[s]-w[t-1])<=1) return dp[s][t]=2;
				else return dp[s][t]=0;
			}
			int tmp=0;
			if(abs(w[s]-w[t-1])<=1 && dfs(dfs,s+1,t-1)==t-s-2){
				return dp[s][t]=t-s;
			}
			rep(i,s+1,t){
				chmax(tmp,dfs(dfs,s,i)+dfs(dfs,i,t));
			}
			return dp[s][t]=tmp;
		};

		int ans=dfs(dfs,0,n);
		cout << ans << endl;

	}


}
accuracy: 1
time_ms: 790
memory_kb: 3840
final_rank: 16

code_snippet: #include<bits/stdc++.h>
#define FOR(i,s,t) for(int i = s; i<t ; i++)
#define SZ(x) (int)x.size()
#define ALL(x) x.begin(), x.end()

using namespace std;

using VI = vector<int>;
using LL = long long;
using VL = vector<LL>;
using VVI = vector<VI>;


int main() {
	int N;
	while (cin >> N, N) {
		VI a(N);
		FOR(i, 0, N) {
			scanf("%d", &a[i]);
		}
		VVI checkdp(N + 1, VI(N + 1, 0));
		VVI dp(N + 1, VI(N + 1, 0));
		int ans = 0;

		FOR(alen, 2, N + 1) {
			FOR(i, 0, N) {
				int j = alen + i - 1;
				if (j >= N) continue;
				if (dp[i + 1][j - 1] == alen - 2 && abs(a[i] - a[j]) <= 1) dp[i][j] = alen;
				FOR(k, i, j) {
					dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j]);
				}
			}
		}
		cout << dp[0][N - 1] << endl;
		//



		//FOR(i, 0, N - 1) {
		//	if (abs(a[i] - a[i + 1]) <= 1) {
		//		checkdp[i][i + 1] = 1;
		//		dp[i][i + 1] = 2;
		//		ans = 2;
		//	}
		//}

		//for (int alen = 4; alen <= N; alen += 2) {// 長さalenを合成
		//	for (int s = 0; s < N; s++) {
		//		for (int spl = s + 1; spl <= N; spl++) {
		//			int end = alen + s - 1;
		//			// checkdp[s][spl], checkdp[spl + 1][end] merge;
		//			// あとで境界処理をすること
		//			if (s < end &&spl < end&& end < N) {// cond
		//				if (checkdp[s][spl] && checkdp[spl + 1][end]) {
		//					checkdp[s][end] = 1;
		//					dp[s][end] = alen;
		//					ans = max(ans, alen);
		//				}
		//				if (abs(a[s] - a[end]) <= 1 && checkdp[s + 1][spl] && checkdp[spl + 1][end - 1]) {
		//					checkdp[s][end] = 1;
		//					dp[s][end] = alen;
		//					ans = max(ans, alen);
		//				}

		//				if (abs(a[s] - a[end]) <= 1 && checkdp[s + 1][end - 1]) {

		//					checkdp[s][end] = 1;
		//					dp[s][end] = alen;
		//					ans = max(ans, alen);
		//				}
		//			}
		//		}
		//	}
		//}
		////cout << "PREANS" << ans << endl;
		////int ss, tt;
		////while (cin >> ss >> tt) {
		////	cout << "(s:" << ss << ",t" << tt << "):" << checkdp[ss][tt] << endl;
		////}
		//// くくりはmergeできたので、O XM O みたいなのを合成する

		//// max / + 

		//for (int alen = 4; alen <= N; alen++) {// 長さalenを合成
		//	for (int s = 0; s < N; s++) {
		//		for (int spl = s + 1; spl <= N; spl++) {
		//			int end = alen + s - 1;
		//			// checkdp[s][spl], checkdp[spl + 1][end] merge;
		//			// あとで境界処理をすること
		//			if (s < end &&spl < end&& end < N) {// cond


		//				dp[s][end] = max({ dp[s][end],dp[s][spl] + dp[spl + 1][end] });
		//				ans = max(ans, dp[s][end]);
		//				/*if (checkdp[s][spl] && checkdp[spl + 1][end]) {
		//					checkdp[s][end] = 1;
		//					dp[s][end] = alen;
		//					ans = max(ans, alen);
		//				}
		//				if (abs(a[s] - a[end]) <= 1 && checkdp[s + 1][spl] && checkdp[spl + 1][end - 1]) {
		//					checkdp[s][end] = 1;
		//					dp[s][end] = alen;
		//					ans = max(ans, alen);
		//				}

		//				if (abs(a[s] - a[end]) <= 1 && checkdp[s + 1][end - 1]) {

		//					checkdp[s][end] = 1;
		//					dp[s][end] = alen;
		//					ans = max(ans, alen);
		//				}*/
		//			}
		//		}
		//	}
		//}

		//cout << ans << endl;

	}



	return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 4172
final_rank: 12

code_snippet: #include <bits/stdc++.h>

using namespace std;

int main() {
  vector<int> res_list;
  while (true) {
    int n; cin >> n;
    if (n == 0) break;
    vector<int> W(n);
    for (int i = 0; i < n; ++i) cin >> W[i];

    vector<vector<int>> dp(n, vector<int>(n, 0));
    for (int l = 2; l <= n; ++l) {
      for (int i = 0; i < n - l + 1; ++i) {
        int j = i + l - 1;
        if (abs(W[i] - W[j]) < 2 && dp[i + 1][j - 1] == l - 2) dp[i][j] = l; 
        for (int k = i; k < j; ++k) {
          dp[i][j] = max(dp[i][j], dp[i][k] + dp[k+1][j]);
        }
      }
    }

    res_list.push_back(dp[0][n-1]);
  }

  for (int res: res_list) cout << res << endl;
  return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 3452
final_rank: 1

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define FOR(i,a,b) for(int (i)=(a);(i)<(b);(i)++)
#define REP(i,n) FOR(i,0,(n))

typedef long long ll;

const int M=10000000;
int dp[400][400];

vector<int>wass;
bool ok(int a, int b){
    return abs(wass[a]-wass[b])<=1;
}
int solve(int l,int r){
    if(dp[l][r]!=-1)return dp[l][r];
    if(l==r)return dp[l][r]=0;
    else if(l==r+1)return dp[l][r]=0;
    else{
        int ans=0;
        for(int p=l+1;p<r;++p){
            ans=max(ans,solve(l,p)+solve(p,r));
        }
        if(ok(l,r-1)){
            if(solve(l+1,r-1)==r-l-2){
                ans=r-l;
            }
        }
        return dp[l][r]=ans;
    }
}
int main()
{
    while(true){
        for(int i=0;i<400;++i){
            for(int j=0;j<400;++j){
                dp[i][j]=-1;
            }
        }
        int N;cin>>N;
        if(!N)break;
        wass.assign(N,0);

        for(int i=0;i<N;++i){
            cin>>wass[i];
        }
        int ans=solve(0,N);
        cout<<ans<<endl;
    }
   
}
accuracy: 1
time_ms: 800
memory_kb: 4000
final_rank: 19

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

int dp[309][309];

int main() {
    while(true){
        int N;
        cin >> N;
        if(N == 0){
            return 0;
        }
        vector<int> weight(N);
        for(int i = 0; i < N; i++){
            cin >> weight[i];
        }
        for(int i = 0; i < N+2; i++){
            for(int j = 0; j < N+2; j++){
                dp[i][j] = 0;
            }
        }
        for(int i = 0; i < N; i++){
            dp[i][i+1] = 0;
        }

        for(int W = 2; W <= N; W++){
            for(int L = 0; L + W <= N; L++){
                int R = L + W;

                if(dp[L+1][R-1] == W-2 && abs(weight[L] - weight[R-1]) <= 1){
                    dp[L][R] = W;
                }

                for(int i = L; i <= R; i++){
                    dp[L][R] = max(dp[L][R], dp[L][i] + dp[i][R]);
                }
            }
        }
        cout << dp[0][N] << endl;
    }
}
accuracy: 1
time_ms: 110
memory_kb: 3808
final_rank: 6

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll = long long;
using Graph = vector<vector<int>>;
const int dx[8] = {1, 0, -1, 0, 1, 1, -1, -1};
const int dy[8] = {0, 1, 0, -1, 1, -1, 1, -1};

#define rep(i, a, b) for(int i = a; i < b; i++)
#define all(v) v.begin(), v.end()
#define YESNO(flag) cout << (flag ? "Yes" : "No") << "\n"
#define inf 1070000000
#define INF 4500000000000000000
#define MOD 998244353
//#define MOD 1000000007
#define pi 3.14159265358979

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;
}

//xのn乗
ll llpow(ll x, ll n) {
    ll ans = 1;
    while(n > 0) {
        if(n & 1) ans *= x;
        x *= x;
        n >>= 1; 
    }
    return ans;
}
ll modpow(ll x, ll n, ll mod) {
    ll ans = 1;
    while(n > 0) {
        if(n & 1) ans = ans * x % mod;
        x = x * x % mod;
        n >>= 1;
    }
    return ans;
}
//nの階乗
ll fact(ll n) {
    if(n == 0) return 1;
    else return n * fact(n-1);
}
//素数判定
bool is_prime(long long x) {
    if(x == 1) return false;
    
    for(long long i = 2; i*i <= x; i++) {
        if(x % i == 0) return false;
    }
    return true;
}

//座標圧縮
vector<int> compress(vector<int> A) {
    vector<int> B = A;

    sort(B.begin(), B.end());
    B.erase(unique(B.begin(), B.end()), B.end());

    vector<int> res(A.size());
    for(int i = 0; i < (int)A.size(); i++) {
        res[i] = lower_bound(B.begin(), B.end(), A[i]) - B.begin();
    }
    return res;
}

//正方形グリッドの右回転
void rotate_right(vector<vector<char>> &S) {
    int N = S.size();
    auto T = S;
    rep(i,0,N) rep(j,0,N) {
        T[i][j] = S[N-1-j][i];
    }
    S = T;
}
//左回転
void rotate_left(vector<vector<char>> &S) {
    int N = S.size();
    auto T = S;
    rep(i,0,N) rep(j,0,N) {
        T[i][j] = S[j][N-1-i];
    }
    S = T;
}

//2点(a,b)と(x,y)の距離
double dist(ll a, ll b, ll x, ll y) {
    return sqrt((a-x)*(a-x) + (b-y)*(b-y));
}
int man(int a, int b, int x, int y) {
    return abs(a-x) + abs(b-y);
}

//桁数
int digit(ll N) {
    if(N <= 9) return 1;

    return 1 + digit(N / 10);
}
//A進数文字列NをB進数に変換. A,Bは10以下
string base_change(string N, ll A, ll B) {
    ll X = stoll(N), Y = 0;

    ll i = 1;
    while(X != 0) {
        Y += (X % 10) * i;
        i *= A;
        X /= 10;
    }

    X = Y, Y = 0;
    i = 1;
    while(X != 0) {
        Y += (X % B) * i;
        i *= 10;
        X /= B;
    }

    return to_string(Y);
}
//回文判定
bool palin(string S) {
    rep(i,0,S.size()) {
        if(S[i] != S[S.size()-1-i]) return false;
    }
    return true;
}


//DFS
void dfs(const Graph &G, int v, vector<bool> &seen) { 
    seen[v] = true;
    
    for (auto next_v : G[v]) { 
        if (!seen[next_v]) {
            dfs(G, next_v, seen);
        }
    }
}
void griddfs(const vector<vector<char>> &G, int x, int y, vector<vector<bool>> &seen) {
    int H = G.size(), W = G[0].size();
    seen[x][y] = true;
    
    for (int i = 0; i < 8; i++) { 
        int nx = x + dx[i], ny = y + dy[i];
        if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
        if (!seen[nx][ny] and G[nx][ny] != '#') griddfs(G, nx, ny, seen);
    }
}
//BFS
void bfs(const Graph &G, int v, vector<int> &dist) {
    rep(i,0,dist.size()) dist[i] = inf;
    dist[v] = 0;
    queue<int> q;
    q.push(v);
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        for(auto next_u : G[u]) {
            if(dist[next_u] == inf) {
                dist[next_u] = dist[u] + 1;
                q.push(next_u);
            }
        }
    }
}
void gridbfs(const vector<vector<char>> &G, int x, int y, vector<vector<int>> &dist) {
    int H = G.size(), W = G[0].size();
    rep(i,0,H) rep(j,0,W) dist[i][j] = inf;
    dist[x][y] = 0;
    queue<pair<int, int>> q;
    q.push(make_pair(x, y));
    while(!q.empty()) {
        int x = q.front().first, y = q.front().second;
        q.pop();
        for(int i = 0; i < 4; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
            if(dist[nx][ny] == inf and G[nx][ny] != '#') {
                dist[nx][ny] = dist[x][y] + 1;
                q.push(make_pair(nx, ny));
            }
        }
    }
}
//ワーシャル・フロイド
void floyd(vector<vector<ll>> &G) {
    int N = G.size();
    for (int k = 0; k < N; k++){
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if(G[i][j] > G[i][k] + G[k][j]) {
                    G[i][j] = G[i][k] + G[k][j];
                }
            }
        }
    }
}

void solve() {
}

int main() {
    while(1) {
        int N; cin >> N;
        if(N == 0) break;
        vector<int> A(N); rep(i,0,N) cin >> A[i];
        vector<vector<int>> dp(N+1, vector<int>(N+1, 0));

        rep(i,0,N) dp[i][i+1] = 0;
        rep(W, 2, N+1) {
            rep(l,0,N) {
                int r = l + W;
                if(r > N) continue;

                if(abs(A[l] - A[r-1]) <= 1 and dp[l+1][r-1] == r-l-2) dp[l][r] = r-l;

                rep(mid,l+1,r) {
                    chmax(dp[l][r], dp[l][mid] + dp[mid][r]);
                }
            }
        }

        cout << dp[0][N] << "\n";
    }
    
    return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 3872
final_rank: 10

code_snippet: #include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cmath>
#include <numeric>
#include <iomanip>
#include <map>
#include <queue>
#include <set>
#include <bitset>
#include <stack>
#include <list>
#include <unordered_set>
#include <unordered_map>
#define rep(i, a, b) for (int i = a; i < b; ++i)
using namespace std;

const int MOD = 998244353;
const int mod = 1000000007;

const long long INF = 1LL << 60;
constexpr double pi = 3.141592653589793238462643383279502884L;

struct Edge {
    int to;
    long long w;
    Edge(int to, long long w) : to(to), w(w) {}
};

using Graph = vector<vector<Edge>>;
using P = pair<int, int>;
using Pll = pair<long long, int>;
using ll = long long;

template<class T> bool chmin(T& a, T b) { if (a > b) { a = b; return true; } else return false; }
template<class T> bool chmax(T& a, T b) { if (a < b) { a = b; return true; } else return false; }

vector<vector<int>> dp;

int rec(int l, int r, const vector<int> &w) {
    // 計算済みの時はその値を返す
    if (dp[l][r] != -1) return dp[l][r];

    // 一個のみの時は取り除けないので取り除かない，つまり0を返す
    if (abs(l - r) <= 1) return 0;

    int res = 0;
    // 区間[l, r)を計算する
    // パターン1: [l, r)までの区間が全部取り除けるとき
    // その中身がすべて1以下で構成されているとき取り除けることになる
    if (abs(w[l] - w[r-1]) <= 1 && rec(l+1, r-1, w) == r - l - 2) {
        // [l, r)を取り除く
        res = r - l;
    }

    // パターン2: 全部取り除かず，区間内でぼちぼち取り除く
    for (int i = l+1; i <= r-1; ++i) {
        // 左側部分での最適な取り除き方をしたときの取り除き個数
        // と右側部分での最適な取り除き方をしたときの取り除き個数
        // を合わせれば今回の[l, r)の最適な取り出し方が得られる
        res = max(res, rec(l, i, w) + rec(i, r, w));
    }

    // メモ化再帰
    return dp[l][r] = res;
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    while (true) {
        int n; cin >> n;
        if (n == 0) break;

        vector<int> w(n);
        for (int i = 0; i < n; ++i) {
            cin >> w[i];
        }

        dp.assign(n+1, vector<int>(n+1, -1));
        cout << rec(0, n, w) << endl;
    }
}
accuracy: 1
time_ms: 700
memory_kb: 3840
final_rank: 15

code_snippet: #include <iostream>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <tuple>
#include <set>
#include <map>
#include <bitset>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <cassert>
#include <unordered_set>
#include <unordered_map>
#include <cmath>
using namespace std;
typedef long long ll;
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define all(v) v.begin(), v.end()

ll llpow(ll a, ll t)
{
  ll res = 1;
  rep(i, t) res *= a;
  return res;
}

ll inf = std::numeric_limits<ll>::max();

int main()
{
  vector<ll> ans;
  while (true)
  {
    ll n;
    cin >> n;
    if (!n)
    {
      break;
    }
    vector<ll> vec(n);
    rep(i, n)
    {
      cin >> vec[i];
    }
    // lrで取り除ける最大
    vector<vector<ll>> dp(n, vector<ll>(n, 0));
    rep(i, n) // diff
    {
      rep(j, n) // left
      {
        if (!i)
        {
          continue;
        }
        if (i + j > n - 1)
        {
          continue;
        }
        if (i == 1)
        {
          if (abs(vec[j] - vec[j + i]) <= 1)
          {
            dp[j][j + i] = 2;
          }
          continue;
        }
        if (dp[j + 1][j + i - 1] == i - 1 && abs(vec[j] - vec[j + i]) <= 1)
        {
          dp[j][j + i] = i + 1;
          continue;
        }
        rep(k, i)
        {
          dp[j][j + i] = max(dp[j][j + i], dp[j][j + k] + dp[j + k + 1][j + i]);
        }
      }
    }
    // cout << dp[0][3] << endl;
    ans.push_back(dp[0][n - 1]);
  }
  for (auto num : ans)
  {
    cout << num << endl;
  }
}
accuracy: 1
time_ms: 150
memory_kb: 3896
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<int, int>;
#define chmin(x, y) x = min(x, y)
#define chmax(x, y) x = max(x, y)

int inf = 10010010;

int main()
{
    while (true)
    {
        int n;
        cin >> n;
        if (n == 0)
            break;
        vector<int> w;
        for (int i = 0; i < n; ++i)
        {
            int a;
            cin >> a;
            w.push_back(a);
        }
        vector<vector<int>> dp(n + 5, vector<int>(n + 5, 0));
        for (int i = 0; i < n - 1; ++i)
        {
            if (abs(w[i] - w[i + 1]) <= 1)
            {
                dp[i][i + 1] = 2;
            }
        }
        for (int i = 0; i < n; ++i)
        {
            for (int j = 0; j < n; ++j)
            {
                int start = j;
                int end = i + j;
                if (end >= n)
                    break;
                for (int k = 1; k < i; ++k)
                {
                    if (dp[start][start + k] != 0 && dp[start + k + 1][end])
                    {
                        dp[start][end] = max(
                            dp[start][end], dp[start][start + k] + dp[start + k + 1][end]);
                    }
                }
                if (dp
                            [start + 1][end - 1] != 0 &&
                    abs(w[start] - w[end]) <= 1)
                {
                    dp[start][end] = max(dp[start][end], dp[start + 1][end - 1] + 2);
                }
            }
        }
        for (int i = 0; i < n; ++i)
        {
            for (int j = 0; j < n; ++j)
            {
                int start = j;
                int end = i + j;
                if (end >= n)
                    break;
                for (int k = 0; k < i; ++k)
                {
                    dp[start][end] = max(
                        dp[start][end], dp[start][start + k] + dp[start + k + 1][end]);
                }
            }
        }
        cout << dp[0][n - 1] << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 3708
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<int, int>;
#define chmin(x, y) x = min(x, y)
#define chmax(x, y) x = max(x, y)

int inf = 10010010;

int main()
{
    while (true)
    {
        int n;
        cin >> n;
        if (n == 0)
            break;
        vector<int> w;
        for (int i = 0; i < n; ++i)
        {
            int a;
            cin >> a;
            w.push_back(a);
        }
        vector<vector<int>> dp(n + 5, vector<int>(n + 5, 0));
        for (int i = 0; i < n - 1; ++i)
        {
            if (abs(w[i] - w[i + 1]) <= 1)
            {
                dp[i][i + 1] = 2;
            }
        }
        for (int i = 0; i < n; ++i)
        {
            for (int j = 0; j < n; ++j)
            {
                int start = j;
                int end = i + j;
                if (end >= n)
                    break;
                for (int k = 0; k < i; ++k)
                {
                    if (dp[start][start + k] != 0 && dp[start + k + 1][end])
                    {
                        dp[start][end] = max(
                            dp[start][end], dp[start][start + k] + dp[start + k + 1][end]);
                    }
                }
                if (dp
                            [start + 1][end - 1] != 0 &&
                    abs(w[start] - w[end]) <= 1)
                {
                    dp[start][end] = max(dp[start][end], dp[start + 1][end - 1] + 2);
                }
            }
        }
        for (int i = 0; i < n; ++i)
        {
            for (int j = 0; j < n; ++j)
            {
                int start = j;
                int end = i + j;
                if (end >= n)
                    break;
                for (int k = 0; k < i; ++k)
                {
                    dp[start][end] = max(
                        dp[start][end], dp[start][start + k] + dp[start + k + 1][end]);
                }
            }
        }
        cout << dp[0][n - 1] << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 3736
final_rank: 9