#include<iostream>
#include<set>
#include<algorithm>
#include<cmath>
#include<complex>
#include<vector>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define ALL(C)     (C).begin(),(C).end()
#define pb         push_back

typedef complex<int> P;

const double eps = 1e-10;

int cross(P a,P b){
  return (a.real()*b.imag()-a.imag()*b.real());
}

double dist(P a){
  return sqrt(a.real()*a.real()+a.imag()*a.imag());
}

double isp(P a,P b,P c){
  return dist(a-c)+dist(b-c)< dist(a-b)+eps;
}

int PolygonArea(P *a,int n){
  int sum = 0;
  rep(i,n){
    sum+=(a[i].real()-a[(i+1)%n].real())*(a[i%n].imag()+a[(i+1)%n].imag());
  }

    
  /*
  cout << "[";
  rep(i,n){
    cout << a[i] <<','<< endl;
  }
  cout << a[0] << ",]"<<endl;
  cout << endl;
  */

  if (sum < 0)sum*=-1;
  if (sum%2 != 0)return -1;
  else return sum/2;
}

bool isok(int n,P *in){
  if (n < 3)return true;

  rep(i,n){
    rep(k,n){
      if (k == i || k == (i+1)%n)continue;
      if (isp(in[i],in[(i+1)%n],in[k])){
	return false;
      }
    }
  }

  //is convex
  //int me = cross(in[1]-in[0],in[2]-in[0]);

    
  if (cross(in[n-2]-in[n-3],in[n-1]-in[n-3]) <0)return false;
  if (cross(in[n-1]-in[n-2],in[0]-in[n-2])   <0)return false;
  if (cross(in[0]-in[n-1],in[1]-in[n-1])     <0)return false;

  return true;
}

bool isconvex(int n,P*in){
  rep(i,n){
    P cur=in[(i+1)%n]-in[i],next=in[(i+2)%n]-in[i];
    int tmp = cross(cur,next);
    if (tmp < 0)return false;
    //if (me*tmp < -eps)return false;
  }
  return true;
}


vector<P> make_cand(int r){
  vector<P> ret;
  for(int x=-r;x<=r;x++){
    double y = sqrt(r*r - x*x);
    if (abs(floor(y)-y)<eps){
      if (y>0.5){
	ret.pb(P(x,(int)y));
	ret.pb(P(x,(int)-y));
      }else ret.pb(P(x,(int)y));
    }
  }
  return ret;
}

int ans;
P ori(0,0);
void search(int n,int now,int pnow,int *len,P *in,vector<P>*cand,
	    double total){

  if (n >=3 && !isconvex(now,in))return;
  //if (!isok(now,in))return;

  if (dist(in[now-1])-total > eps){
    return; 
  }
  
  if (abs(dist(in[now-1])-total)<eps){
    int tmp = PolygonArea(in,now);
    if (isok(n,in))ans=max(ans,tmp);//,cout << tmp<<endl;
    return;    
  }
  

  if (n == pnow+1){
    int index=len[pnow];
    if (abs(dist(in[now-1])-index)<eps ){
      int tmp = PolygonArea(in,now);
      if (isok(n,in))ans=max(ans,tmp);//,cout << tmp<<endl;
    }
    return;
  }

  rep(i,cand[pnow].size()){
    in[now].real()=in[now-1].real()+cand[pnow][i].real();
    in[now].imag()=in[now-1].imag()+cand[pnow][i].imag();
    
    if (in[now].imag()<0 && in[now].real()>=0)continue;
    search(n,now+1,pnow+1,len,in,cand,total-len[pnow]);
  }
}

main(){
  int n;
  while(cin>>n && n){
    int r[n];
    int num[100];
    int len[100];
    int p=0;
    double total=0;
    P in[10];
    vector<P> cand[10];
    
    ans = -1;
    
    rep(i,n){
      cin>>r[i];
      total+=r[i];
    }
    sort(r,r+n);
    in[0]=ori;


    rep(i,n){
      cand[i].clear();
      cand[i]=make_cand(r[i]);
    }

    /*    
    int findmax=0;
    rep(i,n){
      if (cand[i].size() > cand[findmax].size())findmax=i;
      else if (cand[i].size()==cand[findmax].size() &&
	       r[i] > r[findmax])findmax=i;
    }
    
    swap(r[0],r[findmax]);
    sort(r+1,r+n);
    */    
    
    rep(i,cand[0].size()){
      if (cand[0][i].imag() >=0 && cand[0][i].real()>0);
      else {
	cand[0].erase(cand[0].begin()+i);
	i--;
      }
    }

    set<vector<int> >S;
    do{
      
      vector<int> tmp;
      REP(i,1,n){
	tmp.pb(r[i]);
      }
      if (S.find(tmp) != S.end()){
	continue;
      }      
      reverse(ALL(tmp));
      S.insert(tmp);
      

      REP(i,1,n){
	cand[i].clear();
	cand[i]=make_cand(r[i]);
      }
      //      rep(i,n)cout << r[i] <<" ";cout << endl;
      search(n,1,0,r,in,cand,total);
    }while(next_permutation(r+1,r+n));

    cout << ans << endl;
  }
}

Measured memory_bytes: 924