#include <bits/stdc++.h>
using namespace std;
long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); }
long long partition_numbers(const vector<long long>& v, int n,
                            bool nonempty = true) {
  int na = n / 2, nb = n - na;
  long long suma = 0, sumb = 0;
  vector<long long> a(1 << na, 0LL);
  for (int i = (0); i < (na); ++i) {
    int x = (1 << na) - (1 << i), y = (1 << na) - (1 << i);
    suma += v[i];
    while (x < (1 << na) || y < (1 << na))
      if (x < (1 << na) && (y >= (1 << na) || a[x] - v[i] <= a[y] + v[i]))
        a[x + y - (1 << na)] = a[x] - v[i], ++x;
      else
        a[x + y - (1 << na)] = a[y] + v[i], ++y;
  }
  vector<long long> b(1 << nb, 0LL);
  for (int i = (0); i < (nb); ++i) {
    int x = (1 << nb) - (1 << i), y = (1 << nb) - (1 << i);
    int j = na + i;
    sumb += v[j];
    while (x < (1 << nb) || y < (1 << nb))
      if (x < (1 << nb) && (y >= (1 << nb) || b[x] - v[j] <= b[y] + v[j]))
        b[x + y - (1 << nb)] = b[x] - v[j], ++x;
      else
        b[x + y - (1 << nb)] = b[y] + v[j], ++y;
  }
  long long ret = LLONG_MAX;
  auto upd = [&](int ai, int bi) {
    long long cur = abs(a[ai] + b[bi]);
    ret = min(ret, cur);
  };
  int bi = ((int)(b).size());
  bool skipnone = nonempty, skipall = nonempty;
  for (int ai = (0); ai < (((int)(a).size())); ++ai) {
    while (bi - 1 >= 0 && a[ai] + b[bi - 1] >= 0) --bi;
    if (bi < ((int)(b).size())) {
      int ci = bi;
      if (skipnone && a[ai] == -suma && b[ci] == -sumb)
        ++ci, skipnone = false;
      else if (skipall && a[ai] == +suma && b[ci] == +sumb)
        ++ci, skipall = false;
      if (ci < ((int)(b).size())) upd(ai, ci);
    }
    if (bi - 1 >= 0) {
      int ci = bi - 1;
      if (skipnone && a[ai] == -suma && b[ci] == -sumb)
        --ci, skipnone = false;
      else if (skipall && a[ai] == +suma && b[ci] == +sumb)
        --ci, skipall = false;
      if (ci >= 0) upd(ai, ci);
    }
  }
  return ret;
}
struct SubsetConvolution {
  int n;
  vector<int> cnt;
  SubsetConvolution(int _n) {
    n = _n;
    cnt = vector<int>(1 << n);
    cnt[0] = 0;
    for (int mask = (1); mask < (1 << n); ++mask)
      cnt[mask] = cnt[mask >> 1] + (mask & 1);
  }
  void transform(vector<int>& v) {
    for (int step = 1 << (n - 1); step >= 1; step >>= 1)
      for (int base = 0; base < (1 << n); base += step << 1)
        for (int offset = (0); offset < (step); ++offset)
          v[base + step + offset] += v[base + offset];
  }
  void invtransform(vector<int>& v) {
    for (int step = 1 << (n - 1); step >= 1; step >>= 1)
      for (int base = 0; base < (1 << n); base += step << 1)
        for (int offset = (0); offset < (step); ++offset)
          v[base + step + offset] -= v[base + offset];
  }
  int maxDisjointSets(vector<bool> can) {
    vector<vector<int>> one(n + 1, vector<int>(1 << n, 0));
    int mnone = INT_MAX;
    for (int mask = (0); mask < (1 << n); ++mask)
      if (can[mask]) ++one[cnt[mask]][mask], mnone = min(mnone, cnt[mask]);
    assert(mnone >= 1);
    if (mnone == INT_MAX) return 0;
    for (int k = (mnone); k <= (n); ++k) transform(one[k]);
    vector<vector<int>> cur = one;
    int mncur = mnone, ret = 1;
    vector<vector<int>> nxt(n + 1, vector<int>(1 << n, 0));
    while (true) {
      for (int k = (mncur + mnone); k <= (n); ++k)
        for (int mask = (0); mask < (1 << n); ++mask) nxt[k][mask] = 0;
      for (int k = (mncur + mnone); k <= (n); ++k)
        for (int j = (mncur); j <= (k - mnone); ++j)
          for (int mask = (0); mask < (1 << n); ++mask)
            nxt[k][mask] += cur[j][mask] * one[k - j][mask];
      int mnnxt = INT_MAX;
      for (int k = (mncur + mnone); k <= (n); ++k) {
        vector<int> z = nxt[k];
        invtransform(z);
        for (int mask = (0); mask < (1 << n); ++mask)
          if (cnt[mask] == k && z[mask] != 0) {
            mnnxt = k;
            break;
          }
        if (mnnxt != INT_MAX) break;
      }
      if (mnnxt == INT_MAX) return ret;
      swap(cur, nxt);
      mncur = mnnxt;
      ++ret;
    }
  }
};
const int MAXN = 20;
int n;
long long a[MAXN];
long long b[MAXN];
int nb;
int solve() {
  nb = 0;
  for (int i = (0); i < (n); ++i)
    if (a[i] != 0) b[nb++] = a[i];
  vector<bool> can(1 << nb, false);
  vector<long long> v(n);
  for (int mask = (0); mask < (1 << nb); ++mask) {
    if (!can[mask]) {
      int nv = 0;
      long long vsum = 0;
      for (int i = (0); i < (nb); ++i)
        if (mask & (1 << i)) v[nv++] = b[i], vsum += b[i];
      if (nv <= 1 || (vsum + nv - 1) % 2 != 0) continue;
      can[mask] = partition_numbers(v, nv, true) <= nv - 1;
    }
    if (can[mask])
      for (int i = (0); i < (nb); ++i) can[mask | (1 << i)] = true;
  }
  SubsetConvolution sc(nb);
  int save = sc.maxDisjointSets(can);
  return nb - save;
}
void run() {
  scanf("%d", &n);
  for (int i = (0); i < (n); ++i) scanf("%lld", &a[i]);
  printf("%d\n", solve());
}
int main() {
  run();
  return 0;
}
