#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <iomanip>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-7
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005;
typedef pair<int,int> pii;

int N; long long ans;
int r[MAXN], h[MAXN];
long long v[MAXN];
long long seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long long> order;

long double PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long long query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long long v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = (long long) r[i] * r[i] * h[i];
        order.push_back((long long)r[i] * r[i] * h[i]);
    }
    sort(order.begin(), order.end());
    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), (long long) r[i] * r[i] * h[i]) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long long best;
        best = max((long long)0, query(1, 1, N, 1, pl[i]));
        ans = max(ans, best + v[i]);
        update(1, 1, N, min(N, pl[i] + 1), N, best + v[i]);
    }
    cout << setprecision(20) << (long double) ans * PI << endl;
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-6
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005, MOD = 1e9 + 7;
typedef pair<int,int> pii;

int N; long double ans;
int r[MAXN], h[MAXN];
long double v[MAXN];
long double seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long double> order;

long double PI = 3.14159265358979323846264338328;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long double query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long double v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = (long double) r[i] * r[i] * h[i] * PI;
        order.push_back(v[i]);
    }
    sort(order.begin(), order.end());

    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), v[i]) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long double best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = query(1, 1, N, 1, pl[i] - 1);
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    printf("%.6Lf", (ans * 1000000 + 0.5) / 1000000);
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <iomanip>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-7
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005;
typedef pair<int,int> pii;

int N; long long ans;
int r[MAXN], h[MAXN];
long long v[MAXN];
long long seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long long> order;

long double PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long long query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long double v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = (long long) r[i] * r[i] * h[i];
        order.push_back((long long)r[i] * r[i] * h[i]);
    }
    sort(order.begin(), order.end());
    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), (long long) (r[i] * r[i] * h[i])) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long long best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = max((long long)0, query(1, 1, N, 1, pl[i] - 1));
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    cout << setprecision(20) << (long double) ans * PI << endl;
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <iomanip>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-7
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005;
typedef pair<int,int> pii;

int N; long long ans;
int r[MAXN], h[MAXN];
long long v[MAXN];
long long seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long long> order;

long double PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long long query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long long v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = (long long) r[i] * r[i] * h[i];
        order.push_back((long long)r[i] * r[i] * h[i]);
    }
    sort(order.begin(), order.end());
    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), (long long) (r[i] * r[i] * h[i])) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long long best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = max((long long)0, query(1, 1, N, 1, pl[i] - 1));
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    cout << setprecision(20) << (long double) ans * PI << endl;
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-6
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005, MOD = 1e9 + 7;
typedef pair<int,int> pii;

int N; long double ans;
long double r[MAXN], h[MAXN];
long double v[MAXN];
long double seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long double> order;

long double PI = 3.1415926535897932384;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long double query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long double v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = r[i] * r[i] * h[i] * PI;
        order.push_back(v[i]);
    }
    sort(order.begin(), order.end());

    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), v[i]) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long double best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = query(1, 1, N, 1, pl[i] - 1);
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    printf("%.6Lf", ans);
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <iomanip>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-7
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005;
typedef pair<int,int> pii;

int N; long long ans;
int r[MAXN], h[MAXN];
long long v[MAXN];
long double seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long long> order;

long double PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long double query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long double v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = (long double) r[i] * r[i] * h[i];
        order.push_back((long long)r[i] * r[i] * h[i]);
    }
    sort(order.begin(), order.end());
    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), (long long) (r[i] * r[i] * h[i])) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long long best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = query(1, 1, N, 1, pl[i] - 1);
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    printf("%.6Lf", (long double) ans * 4 * PI);
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-6
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005, MOD = 1e9 + 7;
typedef pair<int,int> pii;

int N; long double ans;
int r[MAXN], h[MAXN];
long double v[MAXN];
long double seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long long> order;

long double PI = 3.14159265358979323846264338328;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long double query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long double v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = (long double) r[i] * r[i] * h[i] * PI;
        order.push_back((long long)r[i] * r[i] * h[i]);
    }
    sort(order.begin(), order.end());

    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), v[i]) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long double best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = query(1, 1, N, 1, pl[i] - 1);
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    printf("%.9Lf", ans);
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-6
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005, MOD = 1e9 + 7;
typedef pair<int,int> pii;

int N; long double ans;
int r[MAXN], h[MAXN];
long double v[MAXN];
long double seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long long> order;

long double PI = 3.14159265358979323846264338328;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long double query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long double v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = (long double) r[i] * r[i] * h[i];
        order.push_back((long long)r[i] * r[i] * h[i]);
    }
    sort(order.begin(), order.end());
    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), (long long) (r[i] * r[i] * h[i])) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long double best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = query(1, 1, N, 1, pl[i] - 1);
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    printf("%.15Lf", ans * 4 * atan(1));
}


#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

using namespace std;

typedef long long ll;
const int maxn=1000100;
const int INF=1e9+10;
const double Pi=acos(-1.0);
const double EPS=1e-7;

int n;
int r,h;
ll a[maxn],X[maxn];int Xn;
int b[maxn];
ll Max[maxn];

void push_up(int rt)
{
    Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
}

void build(int l,int r,int rt)
{
    if(l==r){
        Max[rt]=0;
        return;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    push_up(rt);
}

void update(int p,ll c,int l,int r,int rt)
{
    if(l==r){
        Max[rt]=c;
        return;
    }
    int m=(l+r)>>1;
    if(p<=m) update(p,c,lson);
    else update(p,c,rson);
    push_up(rt);
}

ll query(int L,int R,int l,int r,int rt)
{
    if(L>R) return 0;
    if(L<=l&&r<=R) return Max[rt];
    int m=(l+r)>>1;
    ll res=0;
    if(L<=m) res=max(res,query(L,R,lson));
    if(R>m) res=max(res,query(L,R,rson));
    return res;
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif // ONLINE_JUDGE
    while(cin>>n){
        REP(i,1,n) scanf("%d%d",&r,&h),X[i]=a[i]=1LL*r*r*h;
        sort(X+1,X+n+1);
        Xn=unique(X+1,X+n+1)-(X+1);
        REP(i,1,n) b[i]=lower_bound(X+1,X+Xn+1,a[i])-X;
        build(1,Xn,1);
        ll ans;
        REP(i,1,n){
            ll tmp=query(1,b[i]-1,1,Xn,1)+a[i];
            update(b[i],tmp,1,Xn,1);/// change not add
        }
        printf("%.12f\n",Pi*Max[1]);
    }
    return 0;
}


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

int N,q[600],dn[600][600];

int f ( int a , int b ){
	if ( dn[a][b] != -1 )
		return dn[a][b];

	if ( a > b )
		return dn[a][b] = 0;

	if ( a == b )
		return dn[a][b] = 1;

	dn[a][b] = 1e9;
	dn[a][b] = min( dn[a][b] , 1 + f(a+1,b) );
	if ( q[a] == q[a+1] )
		dn[a][b] = min ( dn[a][b] , f( a+2 , b )+1 );

	for ( int i = a+2 ; i <= b ; i++ )
		if ( q[i] == q[a] )
			dn[a][b] = min ( dn[a][b] , f(a+1,i-1)+f(i+1,b) );

	return dn[a][b];
}

int main()
{
	cin >> N;
	for ( int i = 1 ; i <= N ; i++ )
		scanf("%d",&q[i]);

	memset(dn,-1,sizeof dn);
	printf("%d\n",f(1,N));
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<vector<int>,int>
#define ft first
#define sc second

int N;
vector < int > w;
queue < pii > q;
//~ map < vector<int> , int > mp;

int main()
{
	int x;
	cin >> N;
	for ( int i = 1 ; i <= N ; i++ ){
		scanf("%d",&x);
		w.push_back(x);
	}
	q.push( pii ( w,0 ) );

	while( !q.empty() ){
		vector <int> a,b;
		a = q.front().ft;
		int adim = q.front().sc;
		q.pop();
		//~ if ( mp[a]==1 )
			//~ continue;
		//~ mp[a] = 1;
		for ( int i = 0 ; i < a.size() ; i++ )
			for ( int j = i ; j < a.size() ; j++ ){
				int asd = j-i+1,con = 0;
				for ( int k = 0 ; k < asd ; k++ )
					if ( a[i+k] != a[j-k] ){
						con = 1;
						break;
					}
				if ( !con ){
					b = a;
					asd =  j-i+1;
					for ( int k = 1 ; k <= asd ; k++ )
						b.erase(b.begin()+i);
					if (b.empty()){
						printf("%d\n",adim+1);
						return 0;
					}
					q.push( pii (b,adim+1) );
				}
			}
		}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<vector<int>,int>
#define ft first
#define sc second

int N;
vector < int > w;
queue < pii > q;
map < vector<int> , int > mp;

int main()
{
	int x;
	cin >> N;
	for ( int i = 1 ; i <= N ; i++ ){
		scanf("%d",&x);
		w.push_back(x);
	}
	q.push( pii ( w,0 ) );

	while( !q.empty() ){
		vector <int> a,b;
		a = q.front().ft;
		int adim = q.front().sc;
		q.pop();
		if ( mp[a]==1 )
			continue;
		mp[a] = 1;
		for ( int i = 0 ; i < a.size() ; i++ )
			for ( int j = i ; j < a.size() ; j++ ){
				int asd = j-i+1,con = 0;
				for ( int k = 0 ; k < asd ; k++ )
					if ( a[i+k] != a[j-k] ){
						con = 1;
						break;
					}
				if ( !con ){
					b = a;
					asd =  j-i+1;
					for ( int k = 1 ; k <= asd ; k++ )
						b.erase(b.begin()+i);
					if (b.empty()){
						printf("%d\n",adim+1);
						return 0;
					}
					q.push( pii (b,adim+1) );
				}
			}
		}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<vector<int>,int>
#define ft first
#define sc second

int N;
vector < int > w,a,b;
queue < pii > q;
map < vector<int> , int > mp;

int main()
{
	int x;
	cin >> N;
	for ( int i = 1 ; i <= N ; i++ ){
		scanf("%d",&x);
		w.push_back(x);
	}
	q.push( pii ( w,0 ) );

	while( !q.empty() ){
		a = q.front().ft;
		int adim = q.front().sc;
		q.pop();
		if ( mp[a]==1 )
			continue;
		mp[a] = 1;
		for ( int i = 0 ; i < a.size() ; i++ )
			for ( int j = i ; j < a.size() ; j++ ){
				int asd = j-i+1,con = 0;
				for ( int k = 0 ; k < asd ; k++ )
					if ( a[i+k] != a[j-k] ){
						con = 1;
						break;
					}
				if ( !con ){
					b = a;
					asd =  j-i+1;
					for ( int k = 1 ; k <= asd ; k++ )
						b.erase(b.begin()+i);
					if (b.empty()){
						printf("%d\n",adim+1);
						return 0;
					}
					q.push( pii (b,adim+1) );
				}
			}
	}

	return 0;
}


#include <iostream>
#include <vector>
using namespace std;

int n;
int c[510];
vector<int> v[510];
int dp[510][510];
int f(int beg, int end) {
    if (beg >= end)
        return 1;
    if (dp[beg][end])
        return dp[beg][end];
    int ans = 1 + f(beg + 1, end);
    for (int i = 0; i < v[c[beg]].size(); i++) {
        int k = v[c[beg]][i];
        if (k == end)
            ans = min(ans, f(beg + 1, end - 1));
        else if (k > beg && k < end)
            ans = min(ans, f(beg + 1, k - 1) + f(k + 1, end));
    }
    return dp[beg][end] = ans;
}
int main() {
    while (cin >> n) {
        for (int i = 0; i < n; i++) {
            cin >> c[i];
            v[c[i]].push_back(i);
        }
        cout << f(0, n-1) << endl;
    }
    return 0;
}


#include <iostream>
#include <map>
#include <vector>
using namespace std;

int n;
int c[510];
vector<int> v[510];
map<pair<int,int>, int> m;
int f(int beg, int end) {
    if (beg >= end)
        return 1;
    pair<int, int> p = make_pair(beg, end);
    if (m.find(p) != m.end())
        return m[p];
    int ans = 1 + f(beg + 1, end);
    for (int i = 0; i < v[c[beg]].size(); i++) {
        int k = v[c[beg]][i];
        if (k == end)
            ans = min(ans, f(beg + 1, end - 1));
        else if (k > beg && k < end)
            ans = min(ans, f(beg + 1, k - 1) + f(k + 1, end));
    }
    return m[p] = ans;
}
int main() {
    while (cin >> n) {
        for (int i = 0; i < n; i++) {
            cin >> c[i];
            v[c[i]].push_back(i);
        }
        cout << f(0, n-1) << endl;
    }
    return 0;
}


#include <iostream>
#include <map>
#include <vector>
using namespace std;

int n;
int c[510];
vector<int> v[510];
map<pair<int,int>, int> m;
int f(int beg, int end) {
    if (beg > end)
        return 0;
    if (beg == end)
        return 1;
    pair<int, int> p = make_pair(beg, end);
    if (m.find(p) != m.end())
        return m[p];
    int ans = 1 + f(beg + 1, end);
    for (int i = 0; i < v[c[beg]].size(); i++) {
        int k = v[c[beg]][i];
        ans = min(ans, f(beg + 1, k - 1) + f(k + 1, end));
    }
    return m[p] = ans;
}
int main() {
    while (cin >> n) {
        for (int i = 0; i < n; i++) {
            cin >> c[i];
            v[c[i]].push_back(i);
        }
        cout << f(0, n-1) << endl;
    }
    return 0;
}


#include <iostream>
#include <unordered_map>
#include <vector>
using namespace std;

int n;
int c[510];
vector<int> v[510];
unordered_map<pair<int,int>, int> m;
int f(int beg, int end) {
    if (beg >= end)
        return 1;
    pair<int, int> p = make_pair(beg, end);
    if (m.find(p) != m.end())
        return m[p];
    int ans = 1 + f(beg + 1, end);
    for (int i = 0; i < v[c[beg]].size(); i++) {
        int k = v[c[beg]][i];
        if (k == end)
            ans = min(ans, f(beg + 1, end - 1));
        else if (k > beg && k < end)
            ans = min(ans, f(beg + 1, k - 1) + f(k + 1, end));
    }
    return m[p] = ans;
}
int main() {
    while (cin >> n) {
        for (int i = 0; i < n; i++) {
            cin >> c[i];
            v[c[i]].push_back(i);
        }
        cout << f(0, n-1) << endl;
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
int n,a[505],dp[505][505];
int solve(int l,int r) {
	if (l>r) return 1;
	if (~dp[l][r]) return dp[l][r];
	int &ans=dp[l][r];
	ans=1000000007;
	if (a[l]==a[r]) ans=solve(l+1,r-1);
	for(int i=l;i<=r;i++) {
		if (a[l]==a[i]) ans=min(ans,solve(i+1,r)+solve(l+1,i-1));
	}
	return ans;
}
int main() {
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",a+i);
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=n;j++) {
			dp[i][j]=-1;
		}
	}
	printf("%d\n",solve(1,n));
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
int dp[505][505];
int n,a[505];
int solve(int l,int r) {
	if (l==r) dp[l][r]=1;
	if (l+1==r&&a[l]==a[r]) dp[l][r]=1;
	if (l>r) return 0;
	if (~dp[l][r]) return dp[l][r];
	dp[l][r]=n;
	for(int i=l;i<=r;i++) {
		dp[l][r]=min(dp[l][r],solve(l,i)+solve(i+1,r));
	}
	if (a[l]==a[r]) dp[l][r]=min(dp[l][r],solve(l+1,r-1));
	return dp[l][r];
}
int main() {
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	memset(dp,-1,sizeof(dp));
	cout<<solve(1,n)<<endl;
	return 0;
}


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long ll;
const int Maxn=1005,B=999998+315,P=1e9+7;
int n;
int a[Maxn],hash[2][Maxn],Base[Maxn];
int f[Maxn][Maxn],g[Maxn][Maxn]; ////////////////f:diff g:same      i:st j:last
int gethash(int x,int l,int r)
{   if (x==1)
    {
        l=n-l+1,r=n-r+1;
        return (hash[x][l]-(ll)hash[x][r-1]*Base[l-r+1]%P+P)%P;
    }
    return (hash[x][r]-(ll)hash[x][l-1]*Base[r-l+1]%P+P)%P;
}
bool pd(int l,int r)
{   if (gethash(0,l,r)==gethash(1,l,r)) return true;
    return false;
}
int main()
{   //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    int i,j,k,temp;
    scanf ("%d",&n);
    for (i=1;i<=n;i++) scanf ("%d",&a[i]);
    temp=0,Base[0]=1;
    for (i=1;i<=n;i++) temp=((ll)temp*B+a[i])%P,hash[0][i]=temp,Base[i]=(ll)Base[i-1]*B%P;
    temp=0;
    for (i=n;i>=1;i--) temp=((ll)temp*B+a[i])%P,hash[1][n-i+1]=temp;
    memset(f,63,sizeof(f));
    memset(g,63,sizeof(g));
    for (i=1;i<=n;i++) f[i][1]=g[i][1]=1;
    for (i=1;i<n;i++) f[i][2]=1+(a[i]!=a[i+1]),g[i][2]=1+(a[i]!=a[i+1])*(n+4);
    for (j=3;j<=n;j++)
        for (i=1;i<=n;i++)
        {
            g[i][j]=n+5;
            if (a[i]==a[i+j-1])
            {
                g[i][j]=min(g[i][j],g[i+1][j-2]);
                g[i][j]=min(g[i][j],f[i+1][j-2]);
            }
            f[i][j]=n+5;
            for (k=1;k<j;k++)
                f[i][j]=min(f[i][j],f[i][k]+f[i+k][j-k]);
            f[i][j]=min(f[i][j],g[i][j]);
        }
    cout<<f[1][n]<<endl;
    return 0;
}


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long ll;
const int Maxn=505,B=999998+315,P=1e9+7;
int n;
int a[Maxn],hash[2][Maxn],Base[Maxn];
int f[Maxn][Maxn],g[Maxn][Maxn]; ////////////////f:diff g:same      i:st j:last
int gethash(int x,int l,int r)
{   if (x==1)
    {
        l=n-l+1,r=n-r+1;
        return (hash[x][l]-(ll)hash[x][r-1]*Base[l-r+1]%P+P)%P;
    }
    return (hash[x][r]-(ll)hash[x][l-1]*Base[r-l+1]%P+P)%P;
}
bool pd(int l,int r)
{   if (gethash(0,l,r)==gethash(1,l,r)) return true;
    return false;
}
int main()
{   //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    int i,j,k,temp;
    scanf ("%d",&n);
    for (i=1;i<=n;i++) scanf ("%d",&a[i]);
    temp=0,Base[0]=1;
    for (i=1;i<=n;i++) temp=((ll)temp*B+a[i])%P,hash[0][i]=temp,Base[i]=(ll)Base[i-1]*B%P;
    temp=0;
    for (i=n;i>=1;i--) temp=((ll)temp*B+a[i])%P,hash[1][n-i+1]=temp;
    memset(f,63,sizeof(f));
    memset(g,63,sizeof(g));
    for (i=1;i<=n;i++) f[i][1]=g[i][1]=1;
    for (i=1;i<n;i++) f[i][2]=1+(a[i]!=a[i+1]),g[i][2]=1+(a[i]!=a[i+1])*(n+4);
    for (j=3;j<=n;j++)
        for (i=1;i<=n;i++)
        {
            g[i][j]=n+5;
            if (a[i]==a[i+j-1])
            {
                g[i][j]=min(g[i][j],g[i+1][j-2]);
                g[i][j]=min(g[i][j],f[i+1][j-2]);
            }
            f[i][j]=n+5;
            for (k=1;k<j;k++)
                f[i][j]=min(f[i][j],f[i][k]+f[i+k][j-k]);
            f[i][j]=min(f[i][j],g[i][j]);
        }
    cout<<f[1][n]<<endl;
    return 0;
}


//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <set>
using namespace std;
#define w(t) while(t--)
#define S(x) scanf("%d",&x)
#define SLL(x) scanf("%lld",&x)
#define P(x) printf("%d",x)
#define fl(i , a, b) for(i = (int)a; i<(int)b; i++)
#define mem(a , value) memset(a , value , sizeof(a))
#define tr(c, itr) for(itr = (c).begin(); itr != (c).end(); itr++)
#define MOD 1000000007
#define MAX 1000000010
#define ll long long
#define all(v) v.begin(),v.end()
#define mp make_pair
#define pb push_back
typedef pair<int,int> pp;
int c[1234567];
int dp[502][502];
int solve(int i , int j )
{
    int &r = dp[i][j];
    if(r!=-1)
        return r;
    if(i==j)
        return 1;
    if( j - i ==1){
        return c[i] == c[j] ? 1 : 2;
    }
    int ret = MAX ;
    for (int k = i; k < j; ++k)
    {
        ret = min(ret , solve(i , k ) + solve(k+1 , j));
    }
    if(c[i] == c[j])
    {
        ret = min(ret , solve(i +1 , j - 1)) ;
    }
    return r = ret;
}
int main()
{
    //std::ios_base::sync_with_stdio(false);
    int n , i ;
    cin >> n ;
    fl(i , 0, n ){
        cin >> c[i];
    }
    mem(dp , -1) ;
    cout << solve(0 , n-1 )<<endl;
    return 0;
}


//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <set>
using namespace std;
#define w(t) while(t--)
#define S(x) scanf("%d",&x)
#define SLL(x) scanf("%lld",&x)
#define P(x) printf("%d",x)
#define fl(i , a, b) for(i = (int)a; i<(int)b; i++)
#define mem(a , value) memset(a , value , sizeof(a))
#define tr(c, itr) for(itr = (c).begin(); itr != (c).end(); itr++)
#define MOD 1000000007
#define MAX 1000000010
#define ll long long
#define mp make_pair
#define pb push_back
typedef pair<int,int> pp;
int n ;
string s , s1 , tmp , tmp1;
std::vector<pair <int , int > > v;
void make()
{
    v.clear();
    n = s.size();
    for (int i = 0; i < n; ++i)
    {
        tmp = "";
        tmp1 = "";
        for (int j = i; j < n ; ++j)
        {
            tmp+= s[j];
            tmp1 = tmp ;
            reverse(tmp1.begin(), tmp1.end());
            if(tmp1==tmp){
                v.pb(mp( j - i +1 , i )) ;
            }
        }
    }
}
int main()
{
    //std::ios_base::sync_with_stdio(false);

    int i ;
    char ch ;
    cin >> n ;
    fl(i , 0 , n ){
        cin >> ch;
        s+=ch;
    }
    int ans =0 ;
    while(1){
        make();
        sort(v.begin(), v.end());
        pp tmp = v.back();
        int x = tmp.second ;
        int y = tmp.second + tmp.first - 1;
        s = s.substr(0 , x) + s.substr(y+1 , n - y - 1);
        ans++;
        if(s=="")
            break;
    }
    cout << ans << endl;
    return 0;
}


//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <set>
using namespace std;
#define w(t) while(t--)
#define S(x) scanf("%d",&x)
#define SLL(x) scanf("%lld",&x)
#define P(x) printf("%d",x)
#define fl(i , a, b) for(i = (int)a; i<(int)b; i++)
#define mem(a , value) memset(a , value , sizeof(a))
#define tr(c, itr) for(itr = (c).begin(); itr != (c).end(); itr++)
#define MOD 1000000007
#define MAX 1000000010
#define ll long long
#define all(v) v.begin(),v.end()
#define mp make_pair
#define pb push_back
typedef pair<int,int> pp;
int c[1234567];
int dp[502][502];
int solve(int i , int j )
{
    if(i==j)
        return 1;
    if( j - i ==1){
        return c[i] == c[j] ? 1 : 2;
    }
    int ret = MAX ;
    for (int k = i; k < j; ++k)
    {
        ret = min(ret , solve(i , k ) + solve(k+1 , j));
    }
    if(c[i] == c[j])
    {
        ret = min(ret , solve(i +1 , j - 1)) ;
    }
    return dp[i][j] = ret;
}
int main()
{
    //std::ios_base::sync_with_stdio(false);
    int n , i ;
    cin >> n ;
    fl(i , 0, n ){
        cin >> c[i];
    }
    mem(dp , -1) ;
    cout << solve(0 , n-1 )<<endl;
    return 0;
}


#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
using namespace std;

map <string,int> anw;
int prc (string p)
{
    if (p == "") return 0;
    if (anw.count(p)) return anw[p];
    set <string> pal;
    for (int i = 0; i < p.size(); i++)
    {
        string t = "";
        for (int j = i; j < p.size(); j++)
        {
            t += p[j];
            int m = t.size()/2;
            string p1 = t.substr(0,m);
            string p2 = t.substr(m+1);
            reverse(p2.begin(),p2.end());
            if (p1 == p2)
            {
                pal.insert(p.substr(0,i)+p.substr(j+1));
            }
        }
    }
    int r = 1<<20;
    for (set<string> :: iterator it = pal.begin(); it != pal.end(); it++)
    {
        string w = *it;
        r = min(prc(w)+1,r);
    }
    return anw[p] = r;
}

int main()
{
    int n;
    cin >> n;
    string word;
    for (int i = 0; i < n; i++)
    {
        int t;
        cin >> t;
        word += char(t+48);
    }
    cout << prc(word) << endl;
}


#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
using namespace std;

map <string,int> anw;
int prc (string p)
{
    if (p == "") return 0;
    if (anw.count(p)) return anw[p];
    set <string> pal;
    for (int i = 0; i < p.size(); i++)
    {
        string t = "";
        for (int j = i; j < p.size(); j++)
        {
            t += p[j];
            int m = t.size()/2;
            int m1 = (t.size()+1)/2;
            string p1 = t.substr(0,m);
            string p2 = t.substr(m1);
            reverse(p2.begin(),p2.end());
            if (p1 == p2)
            {
                pal.insert(p.substr(0,i)+p.substr(j+1));
            }
        }
    }
    int r = 1<<20;
    for (set<string> :: iterator it = pal.begin(); it != pal.end(); it++)
    {
        string w = *it;
        r = min(prc(w)+1,r);
    }
    return anw[p] = r;
}

int main()
{
    int n;
    cin >> n;
    string word;
    for (int i = 0; i < n; i++)
    {
        int t;
        cin >> t;
        word += char(t+48);
    }
    cout << prc(word) << endl;
}


#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

int arr[510];
int anw[510][510];
int dp (int l, int r)
{
    if (l == r) return 1;
    if (l+1 == r) return arr[l] == arr[r] ? 1 : 2;
    if (anw[l][r] != -1) return anw[l][r];
    int mn = 1<<10;
    if (arr[l] == arr[r]) mn = dp(l+1, r-1);
    for (int i = 0; i < r-l; i++) mn = min(mn,dp(l,l+i)+dp(l+i+1,r));
    return anw[l][r] = mn;
}

int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) cin >> arr[i];
    memset(anw,-1,sizeof(anw));
    cout << dp(0,n-1) << endl;
}


#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

int arr[510];
int anw[510][510];
int dp (int l, int r)
{
    if (l == r) return 1;
    if (l+1 == r) return arr[l] == arr[r] ? 1 : 2;
    if (anw[l][r] != -1) return anw[l][r];
    if (arr[l] == arr[r]) return anw[l][r] = dp(l+1, r-1);
    int mn = 1<<10;
    for (int i = 0; i < r-l; i++) mn = min(mn,dp(l,l+i)+dp(l+i+1,r));
    return anw[l][r] = mn;
}

int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) cin >> arr[i];
    memset(anw,-1,sizeof(anw));
    cout << dp(0,n-1) << endl;
}


#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;

map <string,int> r;
int anw (string p)
{
    if (p == "") return 0;
    set <string> pal;
    for (int i = 0; i < n; i++)
    {
        string t = "";
        for (int j = i; j < n; j++)
        {
            t += p[j];
            int m = t.size()/2;
            string p1 = t.substr(0,m);
            string p2 = t.substr(m+1);
            reverse(p2.begin(),p2.end());
            if (p1 == p2) pal.insert(t);
        }
    }
    for (set<string> :: iterator it = pal.begin(); it != pal.end(); it++)
    {
        string w = *it;
        if (r.count(w) != 0) return r[w];
        return anw(w)+1;
    }
}
int main()
{
    int n;
    cin >> n;
    string word;
    cin >> word;
    for (int i = 0; i < n; i++)
    {
        int t;
        cin >> t;
        word += char(t+48);
    }
    cout << anw(word) << endl;
}


#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<set>
#include<map>
#include<queue>
#define MAX 505
#define inf 0x3f3f3f3f
using namespace std ;
typedef long long ll ;
const double eps =1e-8;

int s[MAX];
int dp[MAX][MAX];

int main()
{
    int n ;
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&s[i]);
    for(int l=1;l<=n;l++)
    {
        for(int a=0;a<n;a++)
        {
            int b=a+l-1;
            if(b>=n) break ;
            if(a==b)  dp[a][b]=1;
            else if(a+1==b)
            {
                if(s[a]==s[b])  dp[a][b]=1;
                else dp[a][b]=2;
            }
            else
            {
                if(s[a]==s[b])
                    dp[a][b]=dp[a+1][b-1];
                else
                {
                    dp[a][b]=inf;
                    for(int c=1+a;c<=b;c++)
                        dp[a][b]=min(dp[a][b],dp[a][c-1]+dp[c][b]);
                }
            }
        }
    }
    printf("%d\n",dp[0][n-1]);
    return 0;
}


#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<set>
#include<map>
#include<queue>
#define MAX 505
#define inf 0x3f3f3f3f
using namespace std ;
typedef long long ll ;
const double eps =1e-8;

int s[MAX];
int dp[MAX][MAX];

int main()
{
    int n ;
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&s[i]);
    for(int l=1;l<=n;l++)
    {
        for(int a=0;a+l-1<n;a++)
        {
            int b=a+l-1;
            if(a==b)  dp[a][b]=1;
            else if(a+1==b)
            {
                if(s[a]==s[b])  dp[a][b]=1;
                else dp[a][b]=2;
            }
            else
            {
                if(s[a]==s[b])
                    dp[a][b]=dp[a+1][b-1];
                else
                    dp[a][b]=inf;
                    for(int c=1+a;c<=b;c++)
                        dp[a][b]=min(dp[a][b],dp[a][c-1]+dp[c][b]);
            }
        }
    }
    printf("%d\n",dp[0][n-1]);
    return 0;
}


#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<set>
#include<map>
#include<queue>
#define MAX 505
#define inf 0x3f3f3f3f
using namespace std ;
typedef long long ll ;
const double eps =1e-8;

int s[MAX];
int dp[MAX][MAX];

int main()
{
    int n ;
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&s[i]);
    for(int l=1;l<=n;l++)
    {
        for(int a=0;a+l-1<n;a++)
        {
            int b=a+l-1;
            if(a==b)  dp[a][b]=1;
            else if(a+1==b)
            {
                if(s[a]==s[b])  dp[a][b]=1;
                else dp[a][b]=2;
            }
            else
            {
                if(s[a]==s[b])
                    dp[a][b]=dp[a+1][b-1];
                else
                {
                    dp[a][b]=inf;
                    for(int c=1+a;c<=b;c++)
                        dp[a][b]=min(dp[a][b],dp[a][c-1]+dp[c][b]);
                }
            }
        }
    }
    printf("%d\n",dp[0][n-1]);
    return 0;
}


#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<set>
#include<map>
#include<queue>
#define MAX 505
#define inf 0x3f3f3f3f
using namespace std ;
typedef long long ll ;
const double eps =1e-8;

int s[MAX];
int dp[MAX][MAX];

int main()
{
    int n ;
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&s[i]);
    for(int l=1;l<=n;l++)
    {
        for(int a=0;a+l-1<n;a++)
        {
            if(a==b)  dp[a][b]=1;
            else if(a+1==b)
            {
                if(s[a]==s[b])  dp[a][b]=1;
                else dp[a][b]=2;
            }
            else
            {
                if(s[a]==s[b])
                    dp[a][b]=dp[a+1][b-1];
                else
                {
                    dp[a][b]=inf;
                    for(int c=1+a;c<=b;c++)
                        dp[a][b]=min(dp[a][b],dp[a][c-1]+dp[c][b]);
                }
            }
        }
    }
    printf("%d\n",dp[0][n-1]);
    return 0;
}


#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<set>
#include<map>
#include<queue>
#define MAX 505
#define inf 0x3f3f3f3f
using namespace std ;
typedef long long ll ;
const double eps =1e-8;

int s[MAX];
int dp[MAX][MAX];

int main()
{
    int n ;
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&s[i]);
    for(int l=1;l<=n;l++)
    {
        for(int a=0;a<n;a++)
        {
            int b=a+l-1;
            if(a==b)  dp[a][b]=1;
            else if(a+1==b)
            {
                if(s[a]==s[b])  dp[a][b]=1;
                else dp[a][b]=2;
            }
            else
            {
                if(s[a]==s[b])
                    dp[a][b]=dp[a+1][b-1];
                else
                {
                    dp[a][b]=inf;
                    for(int c=1+a;c<=b;c++)
                        dp[a][b]=min(dp[a][b],dp[a][c-1]+dp[c][b]);
                }
            }
        }
    }
    printf("%d\n",dp[0][n-1]);
    return 0;
}


#include <string>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <string.h>
#include <utility>
#include <queue>
#include <stack>
#include <iomanip>
#include <ctype.h>
#include <map>
#include <set>
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
#include <iostream>
#include <iomanip>

using namespace std;

typedef long long LL;

#define FOR(i,n) for(int i = 0;i < n;i++)
#define MP make_pair
#define PB push_back
#define ALL(a) (a).begin(),(a).end()
#define PII pair<int, int>
#define PLL pair<long long, long long>
#define CLEAR(a) memset(a, 0, sizeof(a))
#define INF 2000000007
#define y1 uu1
#define y2 uu2
const double EPS = 1E-12;
const double PI = acos(-1.0);
const LL mod = 1000000007;

using namespace std;

int n;
int a[505];
int dp[502][502];
bool ip[502][502];

bool isp(int l, int r) {
	for (int i = 0; i <= (r-l)/2; i++) {
		if (a[l+i] != a[r-i])
			return false;
	}
	return true;
}

inline int get(int l, int r) {
	if (l > r)
		return 0;
	else
	if (dp[l][r])
		return dp[l][r];
	else
	if (ip[l][r])
		return 1;

	int lidx = l, ridx = r;
	dp[l][r] = r-l+1;

	for (int i = l; i <= r-1; i++) {
		dp[l][r] = min(dp[l][r], get(l, i) + get(i+1, r));
	}

	if (a[l] == a[r]) {
		dp[l][r] = min(dp[l][r], get(l+1, r-1));
	}

	return dp[l][r];
}

int main() {
  ios_base::sync_with_stdio(0);
  cin >> n;
  FOR(i,n) cin >> a[i];

  FOR(i,n)
  for (int j = i; j < n; j++) {
  	if (isp(i,j)) {
  		ip[i][j] = true;
  	}
  }

  cout << get(0, n-1) << endl;

  return 0;
}


#include <string>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <string.h>
#include <utility>
#include <queue>
#include <stack>
#include <iomanip>
#include <ctype.h>
#include <map>
#include <set>
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
#include <iostream>
#include <iomanip>

using namespace std;

typedef long long LL;

#define FOR(i,n) for(int i = 0;i < n;i++)
#define MP make_pair
#define PB push_back
#define ALL(a) (a).begin(),(a).end()
#define PII pair<int, int>
#define PLL pair<long long, long long>
#define CLEAR(a) memset(a, 0, sizeof(a))
#define INF 2000000007
#define y1 uu1
#define y2 uu2
const double EPS = 1E-12;
const double PI = acos(-1.0);
const LL mod = 1000000007;

using namespace std;

int n;
short a[505];
vector<short> p[505];
vector<short> bp[505];
short dp[502][502];
bool ip[502][502];

bool isp(int l, int r) {
	for (int i = 0; i <= (r-l)/2; i++) {
		if (a[l+i] != a[r-i])
			return false;
	}
	return true;
}

inline short get(short l, short r) {
	if (l > r)
		return 0;
	else
	if (dp[l][r])
		return dp[l][r];
	else
	if (ip[l][r])
		return 1;

	short lidx = l, ridx = r;
	dp[l][r] = r-l+1;

	while (1) {
		FOR(i, p[lidx].size()) {
			if (p[lidx][i] > ridx)
				break;
			dp[l][r] = min((int)dp[l][r], 1 + get(p[lidx][i] + 1, ridx));
		}

		for (int i = bp[ridx].size() - 1; i >= 0; i--) {
			if (bp[ridx][i] < lidx)
				break;
			dp[l][r] = min((int)dp[l][r], 1 + get(lidx, bp[ridx][i] - 1));
		}

		if (a[lidx] == a[ridx]) {
			lidx++;
			ridx--;
		} else
			break;

		if (lidx > ridx)
			break;
	}

	return dp[l][r];
}

int main() {
  ios_base::sync_with_stdio(0);
  cin >> n;
  FOR(i,n) cin >> a[i];

  FOR(i,n)
  for (int j = i; j < n; j++) {
  	if (isp(i,j)) {
  		p[i].push_back(j);
  		bp[j].push_back(i);
  		ip[i][j] = true;
  	}
  }

  FOR(i,501)
  sort(ALL(bp[i]));

  cout << get(0, n-1) << endl;

  return 0;
}


#include <string>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <string.h>
#include <utility>
#include <queue>
#include <stack>
#include <iomanip>
#include <ctype.h>
#include <map>
#include <set>
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
#include <iostream>
#include <iomanip>

using namespace std;

typedef long long LL;

#define FOR(i,n) for(int i = 0;i < n;i++)
#define MP make_pair
#define PB push_back
#define ALL(a) (a).begin(),(a).end()
#define PII pair<int, int>
#define PLL pair<long long, long long>
#define CLEAR(a) memset(a, 0, sizeof(a))
#define INF 2000000007
#define y1 uu1
#define y2 uu2
const double EPS = 1E-12;
const double PI = acos(-1.0);
const LL mod = 1000000007;

using namespace std;

int n;
int a[505];
vector<int> p[505];
int dp[502][502];
bool ip[502][502];

bool isp(int l, int r) {
	for (int i = 0; i <= (r-l)/2; i++) {
		if (a[l+i] != a[r-i])
			return false;
	}
	return true;
}

inline int get(int l, int r) {
	if (l > r)
		return 0;
	else
	if (dp[l][r])
		return dp[l][r];
	else
	if (ip[l][r])
		return 1;

	int lidx = l, ridx = r;
	dp[l][r] = r-l+1;

	while (1) {
		FOR(i, p[lidx].size()) {
			if (p[lidx][i] > ridx)
				break;
			dp[l][r] = min(dp[l][r], 1 + get(p[lidx][i] + 1, ridx));
		}

		if (a[lidx] == a[ridx]) {
			lidx++;
			ridx--;
		} else
			break;

		if (lidx > ridx)
			break;
	}

	return dp[l][r];
}

int main() {
  ios_base::sync_with_stdio(0);
  cin >> n;
  FOR(i,n) cin >> a[i];

  FOR(i,n)
  for (int j = i; j < n; j++) {
  	if (isp(i,j)) {
  		p[i].push_back(j);
  		ip[i][j] = true;
  	}
  }

  cout << get(0, n-1) << endl;

  return 0;
}


#include <string>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <string.h>
#include <utility>
#include <queue>
#include <stack>
#include <iomanip>
#include <ctype.h>
#include <map>
#include <set>
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
#include <iostream>
#include <iomanip>

using namespace std;

typedef long long LL;

#define FOR(i,n) for(int i = 0;i < n;i++)
#define MP make_pair
#define PB push_back
#define ALL(a) (a).begin(),(a).end()
#define PII pair<int, int>
#define PLL pair<long long, long long>
#define CLEAR(a) memset(a, 0, sizeof(a))
#define INF 2000000007
#define y1 uu1
#define y2 uu2
const double EPS = 1E-12;
const double PI = acos(-1.0);
const LL mod = 1000000007;

using namespace std;

int n;
short a[505];
vector<short> p[505];
short dp[502][502];
bool ip[502][502];

bool isp(int l, int r) {
	for (int i = 0; i <= (r-l)/2; i++) {
		if (a[l+i] != a[r-i])
			return false;
	}
	return true;
}

inline short get(short l, short r) {
	if (l > r)
		return 0;
	else
	if (dp[l][r])
		return dp[l][r];
	else
	if (ip[l][r])
		return 1;

	short lidx = l, ridx = r;
	dp[l][r] = r-l+1;

	while (1) {
		FOR(i, p[lidx].size()) {
			if (p[lidx][i] > ridx)
				break;
			dp[l][r] = min((int)dp[l][r], 1 + get(p[lidx][i] + 1, ridx));
		}

		if (a[lidx] == a[ridx]) {
			lidx++;
			ridx--;
		} else
			break;

		if (lidx > ridx)
			break;
	}

	return dp[l][r];
}

int main() {
  ios_base::sync_with_stdio(0);
  cin >> n;
  FOR(i,n) cin >> a[i];

  FOR(i,n)
  for (int j = i; j < n; j++) {
  	if (isp(i,j)) {
  		p[i].push_back(j);
  		ip[i][j] = true;
  	}
  }

  cout << get(0, n-1) << endl;

  return 0;
}


#include<bits/stdc++.h>

#define pb push_back
#define pp pop_back
#define sz(a) (int)(a.size())
#define F first
#define S second
#define mp make_pair
#define ll long long
#define ull unsigned long long

using namespace std;

const int N = (int)1e6 + 123;
const ll linf = (ll)1e18 + 123;
const int inf = (int)1e9 + 123;
const double eps = 1e-6;

inline void boost()
{
	ios_base::sync_with_stdio(0);
	cin.tie(NULL);
}

int n, a[511], dp[511][511];

int main() {
	boost();
	cin >> n;
	for(int i = 1; i <= n; i ++)
		cin >> a[i];
	for(int i = 1; i <= n; i ++)
		dp[i][i] = 1;
	for(int i = 1; i < n; i ++)
		dp[i][i + 1] = 1 + (a[i] != a[i + 1]);
	for(int dlin = 3; dlin <= n; dlin ++){
		for(int l = 1; l <= n - dlin + 1; l ++){
			int r = l + dlin - 1;
			dp[l][r] = 1 + min(dp[l + 1][r], dp[l][r - 1]);
			for(int k = l + 2; k <= r; k ++){
				if(a[l] == a[r])
					dp[l][r] = min(dp[l][r], dp[l + 1][k - 1] + dp[k + 1][r - 1]);
			}
			if(a[l] == a[l + 1]){
				dp[l][r] = min(dp[l][r], dp[l][l + 1] + dp[l + 2][r]);
			}
		}
	}
	cout << dp[1][n];
	return 0;
}


#include<bits/stdc++.h>

#define pb push_back
#define pp pop_back
#define sz(a) (int)(a.size())
#define F first
#define S second
#define mp make_pair
#define ll long long
#define ull unsigned long long

using namespace std;

const int N = (int)1e6 + 123;
const ll linf = (ll)1e18 + 123;
const int inf = (int)1e9 + 123;
const double eps = 1e-6;

inline void boost()
{
	ios_base::sync_with_stdio(0);
	cin.tie(NULL);
}

ll n, a[511], dp[511][511];

int main() {
	boost();
	cin >> n;
	for(int i = 1; i <= n; i ++)
		cin >> a[i];
	for(int i = 1; i <= n; i ++)
		dp[i][i] = 1;
	for(int i = 1; i < n; i ++)
		dp[i][i + 1] = 1 + (a[i] != a[i + 1]);
	for(int dlin = 3; dlin <= n; dlin ++){
		for(int l = 1; l <= n - dlin + 1; l ++){
			int r = l + dlin - 1;
			dp[l][r] = 1 + min(dp[l + 1][r], dp[l][r - 1]);
			for(int k = l + 2; k <= r; k ++){
				if(a[l] == a[k])
					dp[l][r] = min(dp[l][r], dp[l + 1][k - 1] + dp[k + 1][r]);
			}
			if(a[l] == a[l + 1]){
				dp[l][r] = min(dp[l][r], 1 + dp[l + 2][r]);
			}
		}
	}
	cout << dp[1][n];
	return 0;
}


#include<bits/stdc++.h>

#define pb push_back
#define pp pop_back
#define sz(a) (int)(a.size())
#define F first
#define S second
#define mp make_pair
#define ll long long
#define ull unsigned long long

using namespace std;

const int N = (int)1e6 + 123;
const ll linf = (ll)1e18 + 123;
const int inf = (int)1e9 + 123;
const double eps = 1e-6;

inline void boost()
{
	ios_base::sync_with_stdio(0);
	cin.tie(NULL);
}

ll n, a[511], dp[511][511];

int main() {
	boost();
	cin >> n;
	for(int i = 1; i <= n; i ++)
		cin >> a[i];
	for(int i = 1; i <= n; i ++)
		dp[i][i] = 1;
	for(int i = 1; i < n; i ++)
		dp[i][i + 1] = 1 + (a[i] != a[i + 1]);
	for(int dlin = 3; dlin <= n; dlin ++){
		for(int l = 1; l <= n - dlin + 1; l ++){
			int r = l + dlin - 1;
			dp[l][r] = 1 + min(dp[l + 1][r], dp[l][r - 1]);
			for(int k = l + 2; k <= r; k ++){
				if(a[l] == a[r])
					dp[l][r] = min(dp[l][r], dp[l + 1][k - 1] + dp[k + 1][r - 1]);
			}
			if(a[l] == a[l + 1]){
				dp[l][r] = min(dp[l][r], 1 + dp[l + 2][r]);
			}
		}
	}
	cout << dp[1][n];
	return 0;
}


#include<bits/stdc++.h>

#define pb push_back
#define pp pop_back
#define sz(a) (int)(a.size())
#define F first
#define S second
#define mp make_pair
#define ll long long
#define ull unsigned long long

using namespace std;

const int N = (int)1e6 + 123;
const ll linf = (ll)1e18 + 123;
const int inf = (int)1e9 + 123;
const double eps = 1e-6;

inline void boost()
{
	ios_base::sync_with_stdio(0);
	cin.tie(NULL);
}

ll n, a[511], dp[511][511];

int main() {
	boost();
	cin >> n;
	for(int i = 1; i <= n; i ++)
		cin >> a[i];
	for(int i = 1; i <= n; i ++)
		dp[i][i] = 1;
	for(int i = 1; i < n; i ++)
		dp[i][i + 1] = 1 + (a[i] != a[i + 1]);
	for(int dlin = 3; dlin <= n; dlin ++){
		for(int l = 1; l <= n - dlin + 1; l ++){
			int r = l + dlin - 1;
			dp[l][r] = 1 + min(dp[l + 1][r], dp[l][r - 1]);
			for(int k = l + 2; k <= r; k ++){
				if(a[l] == a[k])
					dp[l][r] = min(dp[l][r], dp[l + 1][k - 1] + dp[k + 1][r - 1]);
			}
			if(a[l] == a[l + 1]){
				dp[l][r] = min(dp[l][r], 1 + dp[l + 2][r]);
			}
		}
	}
	cout << dp[1][n];
	return 0;
}


// TEMPLATE {{{
#include <bits/stdc++.h>
using namespace std;
#ifndef LOCAL
#define OJ 1
#else
#define OJ 0
#endif

#define endl '\n'
#define TIMESTAMP merr << "Execution time: " << (double)clock()/CLOCKS_PER_SEC << " s.\n"
class C_ {}; template <typename T> C_& operator <<(C_& __m, const T& __s) { if (!OJ) cerr << "\E[91m" << __s << "\E[0m"; return __m; }
C_ merr;

struct __s { __s() { if (OJ) { ios_base::Init i; cin.sync_with_stdio(0); cin.tie(0); } } ~__s(){ TIMESTAMP; } } __S;
/// END OF TEMPLATE }}}

int dp[555][555];
int A[555];
int n;
int dp2[555][555];

int rec(int ll, int rr) {
  int sl = ll, sr = rr;
  if (dp[ll][rr] != -1) return dp[ll][rr];
  // while (ll < rr && A[ll] == A[rr]) ll++, rr--;
  if (ll >= rr) return dp[sl][sr] = 0;
  int & ans = dp[sl][sr];
  ans = 1000000000;
  if (A[ll] == A[rr]) ans = rec(ll+1, rr-1);
  ans = min(ans, rec(ll+1, rr)+1);
  for (int i = ll+1; i < rr; i++) {
    ans = min(ans, rec(ll, i)+1 + rec(i+1, rr));
  }
  return ans;
}

int rec2(int ll, int rr) {
  if (dp2[ll][rr] != -1) return dp2[ll][rr];
  int & ans = dp2[ll][rr];
  ans = rec(ll, rr) + 1;
  for (int i = ll; i < rr; i++) {
    ans = min(ans, rec2(ll,i)+rec2(i+1,rr));
  }
  return ans;
}

int main(void) {
  memset(dp, 255, sizeof(dp));
  memset(dp2, 255, sizeof(dp2));
  srand((int)time(0));
  cin >> n;
  // n = 500;
  for (int i = 0; i < n; i++) {
    cin >> A[i];
    // A[i] = rand()%(n/4);
  }
  cout << rec(0, n-1) << endl;
  // for (int i = 0; i < n; i++) {
    // for (int j = i; j < n; j++) {
      // for (int k = i; k <= j; k++) {
        // merr << A[k] << " ";
      // }
      // merr << ": " << rec2(i, j) << endl;
    // }
  // }
  cout << rec2(0, n-1) << endl;
  return 0;
}


// TEMPLATE {{{
#include <bits/stdc++.h>
using namespace std;
#ifndef LOCAL
#define OJ 1
#else
#define OJ 0
#endif

#define endl '\n'
#define TIMESTAMP merr << "Execution time: " << (double)clock()/CLOCKS_PER_SEC << " s.\n"
class C_ {}; template <typename T> C_& operator <<(C_& __m, const T& __s) { if (!OJ) cerr << "\E[91m" << __s << "\E[0m"; return __m; }
C_ merr;

struct __s { __s() { if (OJ) { ios_base::Init i; cin.sync_with_stdio(0); cin.tie(0); } } ~__s(){ TIMESTAMP; } } __S;
/// END OF TEMPLATE }}}

int dp[555][555];
int A[555];
int n;
int dp2[555][555];

int rec(int ll, int rr) {
  int sl = ll, sr = rr;
  if (dp[ll][rr] != -1) return dp[ll][rr];
  while (ll < rr && A[ll] == A[rr]) ll++, rr--;
  if (ll >= rr) return dp[sl][sr] = 0;
  int & ans = dp[sl][sr];
  ans = rec(ll+1, rr)+1;
  for (int i = ll+1; i < rr; i++) {
    ans = min(ans, rec(ll, i)+1 + rec(i+1, rr));
  }
  return ans;
}

int rec2(int ll, int rr) {
  if (dp2[ll][rr] != -1) return dp2[ll][rr];
  int & ans = dp2[ll][rr];
  ans = rec(ll, rr) + 1;
  for (int i = ll; i < rr; i++) {
    ans = min(ans, rec2(ll,i)+rec2(i+1,rr));
  }
  return ans;
}

int main(void) {
  memset(dp, 255, sizeof(dp));
  memset(dp2, 255, sizeof(dp2));
  srand((int)time(0));
  cin >> n;
  // n = 500;
  for (int i = 0; i < n; i++) {
    cin >> A[i];
    // A[i] = rand()%(n/4);
  }
  rec(0, n-1);
  // for (int i = 0; i < n; i++) {
    // for (int j = i; j < n; j++) {
      // for (int k = i; k <= j; k++) {
        // merr << A[k] << " ";
      // }
      // merr << ": " << rec2(i, j) << endl;
    // }
  // }
  cout << rec2(0, n-1) << endl;
  return 0;
}


// TEMPLATE {{{
#include <bits/stdc++.h>
using namespace std;
#ifndef LOCAL
#define OJ 1
#else
#define OJ 0
#endif

#define endl '\n'
#define TIMESTAMP merr << "Execution time: " << (double)clock()/CLOCKS_PER_SEC << " s.\n"
class C_ {}; template <typename T> C_& operator <<(C_& __m, const T& __s) { if (!OJ) cerr << "\E[91m" << __s << "\E[0m"; return __m; }
C_ merr;

struct __s { __s() { if (OJ) { ios_base::Init i; cin.sync_with_stdio(0); cin.tie(0); } } ~__s(){ TIMESTAMP; } } __S;
/// END OF TEMPLATE }}}

int dp[555][555];
int A[555];
int n;
int dp2[555][555];

int rec(int ll, int rr) {
  int sl = ll, sr = rr;
  if (dp[ll][rr] != -1) return dp[ll][rr];
  // while (ll < rr && A[ll] == A[rr]) ll++, rr--;
  if (ll >= rr) return dp[sl][sr] = 0;
  int & ans = dp[sl][sr];
  ans = 1000000000;
  if (A[ll] == A[rr]) ans = rec(ll+1, rr-1);
  ans = min(ans, rec(ll+1, rr)+1);
  for (int i = ll+1; i < rr; i++) {
    ans = min(ans, rec(ll, i)+1 + rec(i+1, rr));
  }
  return ans;
}

int rec2(int ll, int rr) {
  if (dp2[ll][rr] != -1) return dp2[ll][rr];
  int & ans = dp2[ll][rr];
  ans = rec(ll, rr) + 1;
  for (int i = ll; i < rr; i++) {
    ans = min(ans, rec2(ll,i)+rec2(i+1,rr));
  }
  return ans;
}

int main(void) {
  memset(dp, 255, sizeof(dp));
  memset(dp2, 255, sizeof(dp2));
  srand((int)time(0));
  cin >> n;
  // n = 500;
  for (int i = 0; i < n; i++) {
    cin >> A[i];
    // A[i] = rand()%(n/4);
  }
  // cout << rec(0, n-1) << endl;
  // for (int i = 0; i < n; i++) {
    // for (int j = i; j < n; j++) {
      // for (int k = i; k <= j; k++) {
        // merr << A[k] << " ";
      // }
      // merr << ": " << rec2(i, j) << endl;
    // }
  // }
  cout << rec2(0, n-1) << endl;
  return 0;
}


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

int p[maxn];
int cal(int a, int b)
{
    if(a > b) return 0;
    if(a == b) return 1;
    if(b - a == 1)
    {
        if(p[a] == p[b]) return 1;
        return 2;
    }
    if(b - a == 2)
    {
        if(p[a] == p[b]) return 1;
        if(p[a + 1] == p[a] || p[a + 1] == p[b]) return 2;
        return 3;
    }
    for(int i = b; i > a; i--)
        if(p[i] == p[a])
        {
            if(i == a + 1) return 1 + cal(a + 2, b);
            return cal(a + 1, i - 1) + cal(i + 1, b);
        }
    return 1 + cal(a + 1, b);
}

int main()
{
    int n, i, k, h, ret = 0, num = 0;
    scanf("%d", &n);
    for(i = 0; i < n; i++)
        scanf("%d", p + i);
    printf("%d", cal(0, n - 1));
    return 0;
}


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

int p[maxn], dp[maxn][maxn];
bool vit[maxn][maxn];
int cal(int a, int b)
{
    if(vit[a][b]) return dp[a][b];
    vit[a][b] = true;
    int &ret = dp[a][b];
    ret = INT_MAX;
    if(a > b) return ret = 0;
    if(a == b) return ret = 1;
    if(b - a == 1)
    {
        if(p[a] == p[b]) return ret = 1;
        return ret = 2;
    }
    if(b - a == 2)
    {
        if(p[a] == p[b]) return ret = 1;
        if(p[a + 1] == p[a] || p[a + 1] == p[b]) return ret = 2;
        return ret = 3;
    }
    int i;
    for(i = b; i >= a; i--)
        if(p[i] == p[a])
        {
            if(i - a <= 1) ret = min(ret, 1 + cal(a + 2, b));
            else ret = min(ret, cal(a + 1, i - 1) + cal(i + 1, b));
        }
    return ret;
}

int main()
{
    int n, i;
    scanf("%d", &n);
    for(i = 0; i < n; i++)
        scanf("%d", p + i);
    printf("%d", cal(0, n - 1));
    return 0;
}


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

int p[maxn], dp[maxn][maxn];
bool vit[maxn][maxn];
int cal(int a, int b)
{
    if(vit[a][b]) return dp[a][b];
    vit[a][b] = true;
    int &ret = dp[a][b];
    ret = INT_MAX;
    if(a > b) return ret = 0;
    if(a == b) return ret = 1;
    if(b - a == 1)
    {
        if(p[a] == p[b]) return ret = 1;
        return ret = 2;
    }
    if(b - a == 2)
    {
        if(p[a] == p[b]) return ret = 1;
        if(p[a + 1] == p[a] || p[a + 1] == p[b]) return ret = 2;
        return ret = 3;
    }
    int i;
    for(i = b; i >= a; i--)
        if(p[i] == p[a])
        {
            if(i - a <= 1) ret = min(ret, 1 + cal(i + 1, b));
            else ret = min(ret, cal(a + 1, i - 1) + cal(i + 1, b));
        }
    return ret;
}

int main()
{
    int n, i;
    scanf("%d", &n);
    for(i = 0; i < n; i++)
        scanf("%d", p + i);
    printf("%d", cal(0, n - 1));
    return 0;
}


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

int p[maxn], dp[maxn][maxn];
bool vit[maxn][maxn];
int cal(int a, int b)
{
    if(vit[a][b]) return dp[a][b];
    vit[a][b] = true;
    int &ret = dp[a][b];
    ret = INT_MAX;
    if(a > b) return ret = 0;
    if(a == b) return ret = 1;
    if(b - a == 1)
    {
        if(p[a] == p[b]) return ret = 1;
        return ret = 2;
    }
    if(b - a == 2)
    {
        if(p[a] == p[b]) return ret = 1;
        if(p[a + 1] == p[a] || p[a + 1] == p[b]) return ret = 2;
        return ret = 3;
    }
    int i;
    for(i = b; i >= a; i--)
        if(p[i] == p[a])
        {
            if(i - a <= 1) ret = min(ret, 1 + cal(i + 1, b));
            else ret = min(ret, cal(a + 1, i - 1) + cal(i + 1, b));
        }
    return ret;
}

int main()
{
    int n, i;
    scanf("%d", &n);
    for(i = 0; i < n; i++)
        scanf("%d", p + i);
    printf("%d", cal(0, n - 1));
    return 0;
}


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

int p[maxn], dp[maxn][maxn];
bool vit[maxn][maxn];
int cal(int a, int b)
{
    if(a > b) return ret = 0;
    if(vit[a][b]) return dp[a][b];
    vit[a][b] = true;
    int &ret = dp[a][b];
    ret = INT_MAX;
    if(a == b) return ret = 1;
    if(b - a == 1)
    {
        if(p[a] == p[b]) return ret = 1;
        return ret = 2;
    }
    if(b - a == 2)
    {
        if(p[a] == p[b]) return ret = 1;
        if(p[a + 1] == p[a] || p[a + 1] == p[b]) return ret = 2;
        return ret = 3;
    }
    int i;
    for(i = b; i >= a; i--)
        if(p[i] == p[a])
        {
            if(i - a <= 1) ret = min(ret, 1 + cal(i + 1, b));
            else ret = min(ret, cal(a + 1, i - 1) + cal(i + 1, b));
        }
    return ret;
}

int main()
{
    int n, i;
    scanf("%d", &n);
    for(i = 0; i < n; i++)
        scanf("%d", p + i);
    printf("%d", cal(0, n - 1));
    return 0;
}


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

int p[maxn], dp[maxn][maxn];
bool vit[maxn][maxn];
int cal(int a, int b)
{
    if(vit[a][b]) return dp[a][b];
    vit[a][b] = true;
    int &ret = dp[a][b];
    ret = INT_MAX;
    if(a > b) return ret = 0;
    if(a == b) return ret = 1;
    if(b - a == 1)
    {
        if(p[a] == p[b]) return ret = 1;
        return ret = 2;
    }
    if(b - a == 2)
    {
        if(p[a] == p[b]) return ret = 1;
        if(p[a + 1] == p[a] || p[a + 1] == p[b]) return ret = 2;
        return ret = 3;
    }
    int i;
    for(i = b; i > a; i--)
        if(p[i] == p[a])
        {
            if(i == a + 1) ret = min(ret, 1 + cal(a + 2, b));
            else ret = min(ret, cal(a + 1, i - 1) + cal(i + 1, b));
        }
    if(i == a) ret = min(ret, 1 + cal(a + 1, b));
    return ret;
}

int main()
{
    int n, i, k, h, ret = 0, num = 0;
    scanf("%d", &n);
    for(i = 0; i < n; i++)
        scanf("%d", p + i);
    printf("%d", cal(0, n - 1));
    return 0;
}


#include <iostream>
#include <map>
using namespace std;

const int MAXN = 510;
int c[MAXN];
map<pair<int, int>, int> mp;

int dp(int x, int y) {
  if (x > y) return 0;
  if (x == y) return 1;
  pair<int, int> p = make_pair(x, y);
  if (mp.find(p) == mp.end()) {
    int ret = 1 + dp(x+1, y);
    for (int i = x+2; i <= y; i++)
      if (c[x] == c[i])
        ret = min(ret, dp(x+1, i-1) + dp(i+1, y));
    if (c[x] == c[x+1])
      ret = min(ret, 1+dp(x+2, y));
    mp[p] = ret;
  }
  return mp[p];
}

int main() {
  int n;
  cin >> n;
  for (int i = 0; i < n; i++)
    cin >> c[i];
  cout << dp(0, n-1) << endl;
  return 0;
}


#include <iostream>
#include <map>
using namespace std;

const int MAXN = 510;
int c[MAXN];
int dpa[MAXN][MAXN];

int dp(int x, int y) {
  if (x > y) return 0;
  if (x == y) return 1;
  if (dpa[x][y] < 0) {
    int ret = 1 + dp(x+1, y);
    for (int i = x+2; i <= y; i++)
      if (c[x] == c[i])
        ret = min(ret, dp(x+1, i-1) + dp(i+1, y));
    if (c[x] == c[x+1])
      ret = min(ret, 1+dp(x+2, y));
    dpa[x][y] = ret;
  }
  return dpa[x][y];
}

int main() {
  int n;
  cin >> n;
  for (int i = 0; i < n; i++)
    cin >> c[i];
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
      dpa[i][j] = -1;
  cout << dp(0, n-1) << endl;
  return 0;
}


#include <bits/stdc++.h>

#define ll long long int
using namespace std;

static int c[505], dp[505][505];

int calc(int l, int r)
{
    if(l>r)
        return 0;
    if(dp[l][r])
        return dp[l][r];
    if(l==r)
        return dp[l][r] = 1;
    int i,j,k;
    dp[l][r] = r-l+1;
    if(c[l]==c[l+1])
        dp[l][r] = 1 + calc(l+2,r);
    else
        dp[l][r] = 2 + calc(l+2,r);
    for(i=l+2; i<=r; i++)
    {
        if(c[l] == c[i])
            dp[l][r] = min(dp[l][r], calc(l+1,i-1) + calc(i+1,r));
        else
            dp[l][r] = min(dp[l][r], calc(l,i) + calc(i+1,r));
    }
    return dp[l][r];
}

int main()
{
    int i,n;
    scanf("%d",&n);
    for(i=1; i<=n; i++)
        scanf("%d",&c[i]);

    int res = calc(1,n);
    cout<<res<<endl;
    return 0;
}


#include <bits/stdc++.h>

#define ll long long int
using namespace std;

static int c[505], dp[505][505];

int calc(int l, int r)
{
    if(l>r)
        return 0;
    if(dp[l][r])
        return dp[l][r];
    if(l==r)
        return dp[l][r] = 1;
    int i,j,k;
    dp[l][r] = 1 + calc(l+1,r);
    if(c[l]==c[l+1])
        dp[l][r] = min(dp[l][r], 1 + calc(l+2,r));
    else
        dp[l][r] = min(dp[l][r], 2 + calc(l+2,r));

    for(i=l+2; i<=r; i++)
    {
        if(c[l] == c[i])
            dp[l][r] = min(dp[l][r], calc(l+1,i-1) + calc(i+1,r));
        else
            dp[l][r] = min(dp[l][r], calc(l,i) + calc(i+1,r));
    }
    return dp[l][r];
}

int main()
{
    int i,n;
    scanf("%d",&n);
    for(i=1; i<=n; i++)
        scanf("%d",&c[i]);

    int res = calc(1,n);
    cout<<res<<endl;
    return 0;
}


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

int n, c[505], dp[505][505];

int f(int a, int b) {
	if (dp[a][b] != -1) return dp[a][b];
	if (a >= b) dp[a][b] = 1;
	else {
		int m = 1e8;
		if (c[a] == c[b]) m = f(a+1,b-1);
		for (int i = a; i < b; i++) {
			int k = f(a,i) + f(i+1,b);
			m = min(m, k);
		}
		dp[a][b] = m;
	}
	return dp[a][b];
}

int main () {
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		scanf("%d", &c[i]);
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			dp[i][j] = -1;
		}
	}
	printf("%d\n", f(0,n-1));
	return 0;
}


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

int n, c[505], dp[505][505];

int f(int a, int b) {
	if (dp[a][b] != -1) return dp[a][b];
	if (a == b) dp[a][b] = 1;
	else if (a+1 == b) {
		if (c[a] == c[b]) dp[a][b] = 1;
		else dp[a][b] = 2;
	} else {
		int m = 1e8;
		if (c[a] == c[b]) m = f(a+1,b-1);
		for (int i = a; i < b; i++) {
			int k = f(a,i) + f(i+1,b);
			m = min(m, k);
		}
		dp[a][b] = m;
	}
	return dp[a][b];
}

int main () {
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		scanf("%d", &c[i]);
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			dp[i][j] = -1;
		}
	}
	printf("%d\n", f(0,n-1));
	return 0;
}


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define M 505
using namespace std;
int dp[M][M],a[M];
int min(int x,int y){
	if(x==-1)return y;
	return x<y?x:y;
}
int dfs(int l,int r){
	int &p=dp[l][r];
	if(p!=-1)return p;
	if(l>=r)return p=1;
	if(a[l]==a[r])return p=dfs(l+1,r-1);
	bool ok=1;
	for(int i=l;ok&&i<=(l+r)/2;i++){
		if(a[i]!=a[r-i+l])ok=0;
	}
	if(ok)return p=1;
	for(int i=l;i<r;i++){
		p=min(p,dfs(l,i)+dfs(i+1,r));
	}
	return p;
}
int main(){
	int n,i,k,j;
	memset(dp,-1,sizeof(dp));
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",&a[i]);
	printf("%d",dfs(1,n));
	return 0;
}


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define M 505
using namespace std;
int dp[M][M],a[M];
int min(int x,int y){
	if(x==-1)return y;
	return x<y?x:y;
}
int dfs(int l,int r){
	int &p=dp[l][r];
	if(~p)return p;
	if(l>=r)return p=1;
	if(a[l]==a[r])return p=dfs(l+1,r-1);
	bool ok=1;
	for(int i=l;ok&&i<=(l+r)/2;i++){
		if(a[i]!=a[r-i+l])ok=0;
//		if(l==2&&r==3)printf("YES");
	}
	if(ok)return p=1;
	for(int i=l;i<r;i++){
		p=min(p,dfs(l,i)+dfs(i+1,r));
//		if(l==2&&r==3)printf("%d %d %d\n",i,dfs(l,i),dfs(i+1,r));
	}
	return p;
}
int main(){
	int n,i,k,j;
	memset(dp,-1,sizeof(dp));
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",&a[i]);
	printf("%d",dfs(1,n));
	return 0;
}


#include<stdio.h>
#define M 505
int a[M];
int min(int x,int y){
	return x<y?x:y;
}
int dfs(int l,int r){
	if(a[l]==a[r])return dfs(l+1,r-1);
	bool ok=1;
	for(int i=l;ok&&i<=(l+r)/2;i++){
		if(a[i]!=a[r-i+l])ok=0;
	}
	if(ok)return 1;
	int res=20000000;
	for(int i=l;i<r;i++){
		res=min(res,dfs(l,i)+dfs(i+1,r));
	}
	return res;
}
int main(){
	int n,i,k,j;
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",&a[i]);
	printf("%d",dfs(1,n));
	return 0;
}


#include<stdio.h>
#include<string.h>
#define M 505
int a[M],dp[M][M];
int min(int x,int y){
	return x<y?x:y;
}
int dfs(int l,int r){
	if(l>=r)return 1;
	if(a[l]==a[r])return dfs(l+1,r-1);
	bool ok=1;
	if(dp[l][r]==-1){
		for(int i=l;ok&&i<=(l+r)/2;i++){
			if(a[i]!=a[r-i+l])ok=0;
		}
		dp[l][r]=ok;
	}
	if(dp[l][r])return 1;
	int res=20000000;
	for(int i=l;i<r;i++){
		res=min(res,dfs(l,i)+dfs(i+1,r));
	}
	return res;
}
int main(){
	int n,i,k,j;
	memset(dp,-1,sizeof(dp));
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",&a[i]);
	printf("%d",dfs(1,n));
	return 0;
}


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define M 505
using namespace std;
int dp[M][M],a[M];
int min(int x,int y){
	if(x==-1)return y;
	return x<y?x:y;
}
int dfs(int l,int r){
	int &p=dp[l][r];
	if(p!=-1)return p;
	if(l>=r)return p=1;
	if(a[l]==a[r])p=min(p,dfs(l+1,r-1));
	bool ok=1;
	for(int i=l;ok&&i<=(l+r)/2;i++){
		if(a[i]!=a[r-i+l])ok=0;
	}
	if(ok)return p=1;
	for(int i=l;i<r;i++){
		p=min(p,dfs(l,i)+dfs(i+1,r));
	}
	return p;
}
int main(){
	int n,i,k,j;
	memset(dp,-1,sizeof(dp));
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",&a[i]);
	printf("%d",dfs(1,n));
	return 0;
}


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define M 505
using namespace std;
int dp[M][M],a[M];
int min(int x,int y){
	if(x==-1)return y;
	return x<y?x:y;
}
int dfs(int l,int r){
	int &p=dp[l][r];
	if(~p)return p;
	if(l==r)return p=1;
	if(a[l]==a[r])return p=dfs(l+1,r-1);
	bool ok=1;
	for(int i=l;ok&&i<=(l+r)/2;i++){
		if(a[i]!=a[r-i+l])ok=0;
//		if(l==2&&r==3)printf("YES");
	}
	if(ok)return p=1;
	for(int i=l;i<r;i++){
		p=min(p,dfs(l,i)+dfs(i+1,r));
//		if(l==2&&r==3)printf("%d %d %d\n",i,dfs(l,i),dfs(i+1,r));
	}
	return p;
}
int main(){
	int n,i,k,j;
	memset(dp,-1,sizeof(dp));
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",&a[i]);
	printf("%d",dfs(1,n));
	return 0;
}


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define M 505
using namespace std;
int dp[M][M],a[M];
int min(int x,int y){
	if(x==-1)return y;
	return x<y?x:y;
}
int dfs(int l,int r){
	int &p=dp[l][r];
	if(p!=-1)return p;
	if(l>=r)return p=1;
	p=min(p,dfs(l+1,r-1));
	bool ok=1;
	for(int i=l;ok&&i<=(l+r)/2;i++){
		if(a[i]!=a[r-i+l])ok=0;
	}
	if(ok)return p=1;
	for(int i=l;i<r;i++){
		p=min(p,dfs(l,i)+dfs(i+1,r));
	}
	return p;
}
int main(){
	int n,i,k,j;
	memset(dp,-1,sizeof(dp));
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",&a[i]);
	printf("%d",dfs(1,n));
	return 0;
}


#include<stdio.h>
#include<string.h>
#define M 505
int a[M],dp[M][M];
int min(int x,int y){
	return x<y?x:y;
}
int dfs(int l,int r){
	if(l<=r)return 1;
	if(a[l]==a[r])return dfs(l+1,r-1);
	bool ok=1;
	if(dp[l][r]==-1){
		for(int i=l;ok&&i<=(l+r)/2;i++){
			if(a[i]!=a[r-i+l])ok=0;
		}
		dp[l][r]=ok;
	}
	if(dp[l][r])return 1;
	int res=20000000;
	for(int i=l;i<r;i++){
		res=min(res,dfs(l,i)+dfs(i+1,r));
	}
	return res;
}
int main(){
	int n,i,k,j;
	memset(dp,-1,sizeof(dp));
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",&a[i]);
	printf("%d",dfs(1,n));
	return 0;
}


#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define ll long long
#define debug(x) cout<<">value ("<<#x<<") : "<<x<<endl;
#define fr(i,beg,end) for(i=beg;i<end;i++)
#define itfr(it,stl) for(it=stl.begin();it!=stl.end();it++)
#define PII pair<int,int>
#define init(x,val) memset(x,val,sizeof(x))
using namespace std;
int dp[510][510];
int a[510];
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n;
    cin>>n;
    int i,j,k;
    fr(i,0,n)
        cin>>a[i];
    fr(i,0,n)
        dp[i][i]=1;
    fr(i,0,n-1)
    {
        j=i+1;
        if(a[i]==a[j])
            dp[i][j]=1;
        else
            dp[i][j]=2;
    }
    fr(k,3,n+1)
    {
        fr(i,0,n-k+1)
        {
            j=i+k-1;
            int p;
            int c=INT_MAX;
            fr(p,i,j)
                c=min(c,dp[i][p]+dp[p+1][j]);
            dp[i][j]=c;
            if(a[i]==a[j])
                dp[i][j]=min(dp[i][j],dp[i+1][j-1]);
        }
    }
    cout<<dp[0][n-1]<<endl;
    return 0;
}


#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define ll long long
#define debug(x) cout<<">value ("<<#x<<") : "<<x<<endl;
#define fr(i,beg,end) for(i=beg;i<end;i++)
#define itfr(it,stl) for(it=stl.begin();it!=stl.end();it++)
#define PII pair<int,int>
#define init(x,val) memset(x,val,sizeof(x))
using namespace std;
int dp[510][510];
int a[510];
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n;
    cin>>n;
    int i,j,k;
    fr(i,0,n)
        cin>>a[i];
    fr(i,0,n)
        dp[i][i]=1;
    fr(i,0,n-1)
    {
        j=i+1;
        if(a[i]==a[j])
            dp[i][j]=1;
        else
            dp[i][j]=2;
    }
    fr(k,3,n+1)
    {
        fr(i,0,n-k+1)
        {
            j=i+k-1;
            if(a[i]==a[j])
                dp[i][j]=dp[i+1][j-1];
            else
            {
                int p;
                int c=INT_MAX;
                fr(p,i,j)
                    c=min(c,dp[i][p]+dp[p+1][j]);
                dp[i][j]=c;
            }
        }
    }
    cout<<dp[0][n-1]<<endl;
    return 0;
}


#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define ll long long
#define debug(x) cout<<">value ("<<#x<<") : "<<x<<endl;
#define fr(i,beg,end) for(i=beg;i<end;i++)
#define itfr(it,stl) for(it=stl.begin();it!=stl.end();it++)
#define PII pair<int,int>
#define init(x,val) memset(x,val,sizeof(x))
using namespace std;
int dp[501][501];
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n;
    cin>>n;
    int a[n];
    int i,j,k;
    fr(i,0,n)
        cin>>a[i];
    fr(i,0,n)
        dp[i][i]=1;
    fr(i,0,n-1)
    {
        j=i+1;
        if(a[i]==a[j])
            dp[i][j]=1;
        else
            dp[i][j]=2;
    }
    fr(k,3,n+1)
    {
        fr(i,0,n-k+1)
        {
            j=i+k-1;
            if(a[i]==a[j])
                dp[i][j]=dp[i+1][j-1];
            else
            {
                int p;
                int c=INT_MAX;
                fr(p,i,j)
                    c=min(c,dp[i][p]+dp[p+1][j]);
                dp[i][j]=c;
            }
        }
    }
    cout<<dp[0][n-1]<<endl;
    return 0;
}


//In the name of God

#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <cstring>
#include <deque>
using namespace std;
#define mp make_pair
#define lol long long
const int MAXN=510;
int dp[MAXN][MAXN],a[MAXN];

int main()
{
  ios::sync_with_stdio(false);
  int n;
  cin>>n;
  for(int i=0;i<n;i++)
    cin>>a[i];
  for(int i=n-1;i>=0;i--)
    {
      dp[i][i]=1;
      dp[i][i+1]=(a[i]==a[i+1])?1:2;
      for(int j=i+1;j<n;j++)
	{
	  dp[i][j]=dp[i+1][j]+1;
	  for(int k=i+1;k<=j;k++)
	    if(a[i]==a[k])
	      {
		if(k-1>=i+1)
		  dp[i][j]=min(dp[i][j],dp[i+1][k-1]+dp[k+1][j]);
		else
		  dp[i][j]=min(dp[i][j],dp[k+1][j]+1);
	      }
	}
    }
  cout<<dp[0][n-1]<<endl;
  return 0;
}


//In the name of God

#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <cstring>
#include <deque>
using namespace std;
#define mp make_pair
#define lol long long
const int MAXN=510;
bool p[MAXN][MAXN];
deque <int> v;

int main()
{
  ios::sync_with_stdio(false);
  int n;
  cin>>n;
  for(int i=0;i<n;i++)
    {
      int x;
      cin>>x;
      v.push_back(x);
    }
  int ans=0;
  bool dosar=false;
  while(v.size()>1)
    {
      if(v.back()==v.front())
	{
	  v.pop_back();
	  v.pop_front();
	  dosar=true;
	}
      else
	{
	  int len=0,x=0,y=0;
	  memset(p,0,sizeof p);
	  for(int i=v.size()-1;i>=0;i--)
	    {
	      p[i][i]=true;
	      if(i!=v.size()-1)
		p[i][i+1]=(v[i]==v[i+1]);
	      for(int j=i+2;j<v.size();j++)
		p[i][j]=p[i+1][j-1]*(v[i]==v[j]);
	      for(int j=i;j<v.size();j++)
		if(p[i][j] and j-i+1>len)
		  len=j-i+1,x=i,y=j;
	    }
	  for(int i=x;i<=y;i++)
	    v.erase(v.begin()+x);
	  ans++;
	}
    }
  cout<<ans+dosar<<endl;
  return 0;
}


//In the name of God

#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <cstring>
#include <deque>
using namespace std;
#define mp make_pair
#define lol long long
const int MAXN=510;
bool p[MAXN][MAXN];
deque <int> v;

int main()
{
  ios::sync_with_stdio(false);
  int n;
  cin>>n;
  for(int i=0;i<n;i++)
    {
      int x;
      cin>>x;
      v.push_back(x);
    }
  int ans=0;
  bool dosar=false;
  while(v.size()>1)
    {
      if(v.back()==v.front())
	{
	  v.pop_back();
	  v.pop_front();
	  dosar=true;
	}
      else
	{
	  int len=0,x=0,y=0;
	  memset(p,0,sizeof p);
	  for(int i=v.size()-1;i>=0;i--)
	    {
	      p[i][i]=true;
	      if(i!=v.size()-1)
		p[i][i+1]=(v[i]==v[i+1]);
	      for(int j=i+2;j<v.size();j++)
		p[i][j]=p[i+1][j-1]*(v[i]==v[j]);
	      for(int j=i;j<v.size();j++)
		if(p[i][j] and j-i+1>len)
		  len=j-i+1,x=i,y=j;
	    }
	  for(int i=x;i<=y;i++)
	    v.erase(v.begin()+x);
	  ans++;
	}
    }
  if(v.size()==1)
    dosar=true;
  cout<<ans+dosar<<endl;
  return 0;
}


#include <iostream>
#include <vector>
using namespace std;
int n;
int main(){
	cin >> n;
	vector<vector<int> > res(n + 1);
	vector<int> r(n);
	for (int i = 0; i < n; i++)cin >> r[i];
	for (int i = 0; i < n + 1; i++){
		vector<int> v(n + 1);
		for (int j = 0; j < n + 1; j++){
			if (j == i + 1 or j == i) v[j] = 1;
			else v[j] = 0;
		}
		res[i] = v;
	}

	for (int s = 2; s < n + 1; s++){
		for (int beg = 0; beg < n - s + 1; beg++){
			int maxi = 501;
			if (r[beg] == r[beg + s - 1]){
				maxi = res[beg + 1][beg + s - 1];
				//cout << beg << beg + s << maxi << endl;
			}
			for (int i = beg + 1; i < beg + s; i++){
				int a = res[beg][i] + res[i][beg + s];
				//cout << i <<' ' << beg + s << endl;
				if (a < maxi) maxi = a;
			}
			res[beg][beg + s] = maxi;
		}
	}
	cout << res[0][n];
	//cout << res[1][2];
	system("PAUSE");
	return 0;
}


#include <iostream>
#include <vector>
using namespace std;
int n;
int main(){
	cin >> n;
	vector<vector<int> > res(n + 1);
	vector<int> r(n);
	for (int i = 0; i < n; i++)cin >> r[i];
	for (int i = 0; i < n + 1; i++){
		vector<int> v(n + 1);
		for (int j = 0; j < n + 1; j++){
			if (j == i + 1 or j == i) v[j] = 1;
			else v[j] = 0;
		}
		res[i] = v;
	}

	for (int s = 2; s < n + 1; s++){
		for (int beg = 0; beg < n - s + 1; beg++){
			int maxi = 501;
			if (r[beg] == r[beg + s - 1]){
				maxi = res[beg + 1][beg + s - 1];
				//cout << beg << beg + s << maxi << endl;
			}
			for (int i = beg + 1; i < beg + s; i++){
				int a = res[beg][i] + res[i][beg + s];
				//cout << i <<' ' << beg + s << endl;
				if (a < maxi) maxi = a;
			}
			res[beg][beg + s] = maxi;
		}
	}
	cout << res[0][n];
	//cout << res[1][2];
	return 0;
}


#include <iostream>
#include <fstream>
#include <cstring>
#include <algorithm>
using namespace std;
ifstream f("test.in");
ofstream g("test.out");
 int n,a[505],dp[505][505];
int main()
{ int i,x,y,t,len,sol;
  cin>>n;
  for(i=1;i<=n;i++)
   cin>>a[i];

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

 for(i=1;i<=n;i++)
  {dp[i][i]=1;
   if (i<n)
   { if(a[i]==a[i+1]) dp[i][i+1]=1;
      else dp[i][i+1]=2;
   }
  }

 for(len=3;len<=n;len++)
  {
   for(i=1;i<=n-len+1;i++)
   {
     x=i; y=i+len-1;
      dp[x][y]=min(dp[x][y],dp[x+1][y]+1);
      if (a[x]==a[x+1]) dp[x][y]=min(dp[x][y],dp[x+2][y]+1);

      for(t=x+2;t<=y;t++)
      { if (a[x]==a[t])
         { sol=dp[x+1][t-1];
           if (t<y) sol+=dp[t+1][y];
          dp[x][y]=min(dp[x][y],sol);
         }
      }
   }
  }

  cout<<dp[1][n];
    return 0;
}


#include <iostream>
#include <fstream>
#include <cstring>
#include <algorithm>
using namespace std;
ifstream f("test.in");
ofstream g("test.out");
 int n,a[505],dp[505][505];
int main()
{ int i,x,y,t,len,sol;
  cin>>n;
  for(i=1;i<=n;i++)
   cin>>a[i];

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

 for(i=1;i<=n;i++)
  {dp[i][i]=1;
   if (i<n && a[i]==a[i+1]) dp[i][i+1]=1;
  }

 for(len=2;len<=n;len++)
  {
   for(i=1;i<=n;i++)
   {
     x=i; y=i+len-1;
      dp[x][y]=min(dp[x][y],dp[x+1][y]+1);
      if (a[x]==a[x+1]) dp[x][y]=min(dp[x][y],dp[x+2][y]+1);
     if (len>2)
      for(t=x+2;t<=y;t++)
      { if (a[x]==a[t])
         { sol=dp[x+1][t-1];
           if (t<y) sol+=dp[t+1][y];
          dp[x][y]=min(dp[x][y],sol);
         }
      }
   }
  }

  cout<<dp[1][n];
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

int odd(deque<int>& d, int pos)
{
	int ret = 1;
	int i = pos-1;
	int j = pos+1;

	while(i >= 0 and j < d.size() and d[i] == d[j])
	{
		i--;
		j++;
		ret+=2;
	}
	return ret;
}

int even(deque<int>& d, int pos)
{
	int ret = 0;
	int i = pos;
	int j = pos+1;

	while(i >= 0 and j < d.size() and d[i] == d[j])
	{
		i--;
		j++;
		ret+=2;
	}
	return ret;
}

/*
int best_odd(deque<int>& d)
{
	int mx = 1;
	int ret = 0;
	for (int i = 0; i < d.size(); i++)
	{
		int cur = odd(i);
		if (cur > mx)
		{
			mx = cur;
			ret = i;
		}
	}
	return ret;
}

int best_even(deque<int>& d)
{
	int mx = 0;
	int ret = 0;
	for (int i = 0; i < d.size(); i++)
	{
		int cur = even(i);
		if (cur > mx)
		{
			mx = cur;
			ret = i;
		}
	}
	return ret;
}
*/
void erase(deque<int>& d, int i, int j)
{
	d.erase(d.begin()+i, d.begin()+j+1);
}

int solve(deque<int>& d)
{
	if (d.size() == 0)
		return 0;

	int ret = 0x3f3f3f3f;

	for (int i = 0; i < d.size(); i++)
	{
		deque<int> od, ed;
		od = d;
		ed = d;
		int so = odd(d, i);
		int se = even(d, i);
		erase(od, i-so/2, i+so/2);
		ret = min(ret, 1+solve(od));
		if(se)
		{
			erase(ed, i-(se/2)+1,i + se/2);
			ret = min(ret, 1+solve(ed));
		}

	}
	return ret;
}

int main()
{
	int n;

	scanf("%d", &n);

	deque<int> d;
	for (int i = 0; i < n; i++)
	{
		int x;
		scanf("%d", &x);
		d.push_back(x);
	}

	int ans = solve(d);

	printf("%d\n", ans);
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

deque<int> d;

int odd(int pos)
{
	int ret = 1;
	int i = pos-1;
	int j = pos+1;

	while(i >= 0 and j < d.size() and d[i] == d[j])
	{
		i--;
		j++;
		ret+=2;
	}
	return ret;
}

int even(int pos)
{
	int ret = 0;
	int i = pos;
	int j = pos+1;

	while(i >= 0 and j < d.size() and d[i] == d[j])
	{
		i--;
		j++;
		ret+=2;
	}
	return ret;
}

int best_odd()
{
	int mx = 1;
	int ret = 0;
	for (int i = 0; i < d.size(); i++)
	{
		int cur = odd(i);
		if (cur > mx)
		{
			mx = cur;
			ret = i;
		}
	}
	return ret;
}

int best_even()
{
	int mx = 0;
	int ret = 0;
	for (int i = 0; i < d.size(); i++)
	{
		int cur = even(i);
		if (cur > mx)
		{
			mx = cur;
			ret = i;
		}
	}
	return ret;
}

void erase(int i, int j)
{
	d.erase(d.begin()+i, d.begin()+j+1);
}

int main()
{
	int n;

	scanf("%d", &n);

	for (int i = 0; i < n; i++)
	{
		int x;
		scanf("%d", &x);
		d.push_back(x);
	}

	int ans = 0;
	while(!d.empty())
	{
		int o = best_odd();
		int e = best_even();

		int so = odd(o);
		int se = even(e);

		//printf("o = %d (size %d), e = %d (size %d)\n", o, so, e, se);
		if (so > se)
		{
			erase(o - so/2, o + so/2);
		}
		else
		{
			erase(e-(se/2)+1, e+se/2);
		}
		ans++;
	}
	printf("%d\n", ans);
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

vector<int> v;
int pd[510][510];

int solve(int i, int j)
{
	if (i == j)
		return 1;

	if (j == i+1 and v[i] == v[j])
		return 1;

	if (i > j)
		return 0;

	if (pd[i][j] != -1)
		return pd[i][j];

	int ans = 0x3f3f3f3f;

	if (v[i] == v[j])
		ans = solve(i+1, j-1);

	for (int d = i; d+1 <= j; d++)
	{
		ans = min(ans, solve(i, d) + solve(d+1, j));
	}
	return pd[i][j] = ans;
}

int main()
{
	int n;

	scanf("%d", &n);

	for (int i = 0; i < n; i++)
	{
		int x;
		scanf("%d", &x);
		v.push_back(x);
	}

	memset(pd, -1, sizeof(pd));

	printf("%d\n", solve(0, n-1));
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

int odd(deque<int>& d, int pos)
{
	int ret = 1;
	int i = pos-1;
	int j = pos+1;

	while(i >= 0 and j < d.size() and d[i] == d[j])
	{
		i--;
		j++;
		ret+=2;
	}
	return ret;
}

int even(deque<int>& d, int pos)
{
	int ret = 0;
	int i = pos;
	int j = pos+1;

	while(i >= 0 and j < d.size() and d[i] == d[j])
	{
		i--;
		j++;
		ret+=2;
	}
	return ret;
}

int best_odd(deque<int>& d)
{
	int mx = 1;
	int ret = 0;
	for (int i = 0; i < d.size(); i++)
	{
		int cur = odd(d, i);
		if (cur > mx)
		{
			mx = cur;
			ret = i;
		}
	}
	return ret;
}

int best_even(deque<int>& d)
{
	int mx = 0;
	int ret = 0;
	for (int i = 0; i < d.size(); i++)
	{
		int cur = even(d, i);
		if (cur > mx)
		{
			mx = cur;
			ret = i;
		}
	}
	return ret;
}

void erase(deque<int>& d, int i, int j)
{
	d.erase(d.begin()+i, d.begin()+j+1);
}

int solve(deque<int>& d)
{
	if (d.size() == 0)
		return 0;

	int ret = 0x3f3f3f3f;
	deque<int> od, ed;
	od = d;
	ed = d;
	int o = best_odd(d);
	int e = best_even(d);

	int so = odd(d, o);
	int se = even(d, e);

	erase(od, o-so/2, o+so/2);
	ret = min(ret, 1+solve(od));

	if(se)
	{
		erase(ed, e-(se/2)+1,e + se/2);
		ret = min(ret, 1+solve(ed));
	}

	return ret;
}

int main()
{
	int n;

	scanf("%d", &n);

	deque<int> d;
	for (int i = 0; i < n; i++)
	{
		int x;
		scanf("%d", &x);
		d.push_back(x);
	}

	int ans = solve(d);

	printf("%d\n", ans);
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

vector<int> v;
int pd[510][510];

bool isPal(int i, int j)
{
	while (i < j)
	{
		if (v[i] != v[j])
			return false;
		i++;
		j--;
	}
	return true;
}

bool isPal2(int i1, int j1, int i2, int j2)
{
	vector<int> s;

	if (i1 > j1 or i2 > j2)
		return false;

	for (int i = i1; i <= j1; i++)
		s.push_back(v[i]);

	for (int i = i2; i <= j2; i++)
		s.push_back(v[i]);

	vector<int> ss = s;
	reverse(s.begin(), s.end());
	return (s == ss);
}

int solve(int i, int j)
{
	if (i == j)
		return 1;

	if (i > j)
		return 0;

	if (pd[i][j] != -1)
		return pd[i][j];

	int ans = 1 + solve(i+1, j);

	if (v[i] == v[i+1])
		ans = min(ans, 1 + solve(i+2, j));

	for (int d = i+2; d <= j; d++)
	{
		if(v[i] == v[d])
			ans = min(ans, solve(i+1, d-1) + solve(d+1, j));
	}
	return pd[i][j] = ans;
}

int main()
{
	int n;

	scanf("%d", &n);

	for (int i = 0; i < n; i++)
	{
		int x;
		scanf("%d", &x);
		v.push_back(x);
	}

	memset(pd, -1, sizeof(pd));

	printf("%d\n", solve(0, n-1));
	return 0;
}


//In the Name of God

#include<iostream>
#include<cstdio>
#include<cstring>
#define int long long

using namespace std;

int n,inf;
int a[550];
int dp[550][550];

int f(int l,int r)
{
  int ret=0;
  while(l<r)
    if(a[l]==a[r])
      ret++,l++,r--;
    else
      break;
  return ret;
}

int DP(int l,int r)
{
  if(dp[l][r]!=inf)
    return dp[l][r];
  if(l==r)
    return dp[l][r]=1;
  if(l>r)
    return dp[l][r]=0;
  int c=f(l,r);
  if(c)
    if(l+c>=r-c)
      dp[l][r]=1;
    else
      dp[l][r]=DP(l+c,r-c);
  for(int i=l;i<r;i++)
    dp[l][r]=min(dp[l][r],DP(l,i)+DP(i+1,r));
  return dp[l][r];
}

main()
{
  cin>>n;
  for(int i=0;i<n;i++)
    cin>>a[i];
  memset(dp,31,sizeof dp);
  inf=dp[0][0];
  cout<<min(DP(0,n-1),n)<<endl;
  return 0;
}


//In the Name of God

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

int n,inf;
int a[550];
int dp[550][550];

int f(int l,int r)
{
  int ret=0;
  while(l<r)
    if(a[l]==a[r])
      ret++,l++,r--;
    else
      break;
  return ret;
}

int DP(int l,int r)
{
  if(dp[l][r]!=inf)
    return dp[l][r];
  if(l==r)
    return dp[l][r]=1;
  if(l>r)
    return dp[l][r]=0;
  int c=f(l,r),L=r-l+1;
  if(c)
    if(l+c>=r-c)
      dp[l][r]=1;
    else
      dp[l][r]=DP(l+c,r-c);
  for(int i=l;i<r;i++)
    dp[l][r]=min(dp[l][r],DP(l,i)+DP(i+1,r));
  return dp[l][r];
}

main()
{
  scanf("%d",&n);
  for(int i=0;i<n;i++)
    scanf("%d",a+i);
  memset(dp,31,sizeof dp);
  inf=dp[0][0];
  cout<<DP(0,n-1)<<endl;
  return 0;
}


//In the Name of God

#include<iostream>
#include<cstdio>
#include<cstring>
#define int long long

using namespace std;

int n,inf;
int a[550];
int dp[550][550];

int DP(int l,int r)
{
  if(dp[l][r]!=inf)
    return dp[l][r];
  if(l>r)
    return dp[l][r]=0;
  if(a[l]==a[r])
    dp[l][r]=max(1ll,DP(l+1,r-1));
  for(int i=l;i<r;i++)
    dp[l][r]=min(dp[l][r],DP(l,i)+DP(i+1,r));
  return dp[l][r];
}

main()
{
  cin>>n;
  for(int i=0;i<n;i++)
    cin>>a[i];
  memset(dp,31,sizeof dp);
  inf=dp[0][0];
  cout<<DP(0,n-1)<<endl;
  return 0;
}