// Original C++ solution (slower):
#include <iostream>

#include <bits/stdc++.h>

using namespace std;



typedef vector<int> vi;

typedef bitset<20> MASK;

#define ll long long

#define PI 3.14159265359

//#define x first

#define y second

#define point pair<int,int>

#define clr(x, val)	memset((x), (val), sizeof(x))



//you don't know math, unless you can do math!

ll a[17][17];

ll cost[1 << 17];

vector<vector<ll>> masks;

ll n;

ll dp[1 << 17];

ll OO = 1e15;

ll solve(MASK mask){

    if(mask.count() == n)

        return 0;



    ll &ret = dp[mask.to_ulong()];

    if(ret != -1)

        return ret;



    ret = -OO;

    for(int i = 0; i < masks[mask.to_ulong()].size(); i++){

        ll c = cost[masks[mask.to_ulong()][i]];

        MASK new_mask = mask.to_ulong() | masks[mask.to_ulong()][i];



        ret = max(ret, solve(new_mask) + c);

    }



    return ret;

}



int main(){

    cin.tie(0);

    cin.sync_with_stdio(0);



    clr(dp, -1);

    cin>>n;

    masks = vector<vector<ll>> (1 << (n + 1));

    for(int i = 0; i < n; i++)

        for(int j = 0; j < n; j++)

            cin>>a[i][j];



    for(ll i = 0; i <= (1 << n); i++){

        MASK mask = i;

        ll ccost = 0;

        for(int k = 0; k < n; k++){

            if(!mask[k]) continue;

            for(int j = k + 1; j < n; j++){

                if(mask[j])

                    ccost+= a[k][j];

            }

        }



        cost[i] = ccost;

    }



    for(ll i = 0; i <= (1 << n); i++){

        MASK mask = i;

        mask.flip();

        int maskCopy = mask.to_ulong() & ((1 << n) - 1);



        for(int sub = maskCopy; sub > 0; sub = (sub - 1) & maskCopy){

            masks[i].push_back(sub);

        }

    }



    cout<<solve(0);

}


// Optimized solution to the same problem (faster):
// Author : Mohamed Sameh

#include <bits/stdc++.h>

typedef long long ll ;

#define pb push_back

#define f first

#define s second

#define all(v) v.begin(),v.end()

#define rall(v) v.rbegin(),v.rend()

#define SZ(a) (int)a.size()

#define Flush fflush(stdout);

using namespace std ;

const int N = 16;

const ll MN = -1e9*N;

int n;

int a[N][N];

ll dp[(1<<N)];

ll value[(1<<N)];

int arr[N];

ll solve(int msk = (1<<n)-1)

{

  if (!msk)return 0;

  ll &ret = dp[msk];

  if (~ret)return ret;

  ret = MN;

  for (int cur_msk = msk; cur_msk; cur_msk=(cur_msk-1)&msk)

  {

    ret = max(ret, value[cur_msk] + solve(msk^cur_msk));

  }

  return ret;

}

ll get_cost(int sz)

{

  ll ret = 0;

  for (int i = 0; i < sz; i++)

    for (int j = i+1; j < sz; j++)

      ret += a[arr[i]][arr[j]];

  return ret;

}

int main()

{

  scanf("%d", &n);

  for (int i = 0; i < n; i++)

    for (int j = 0; j < n; j++)

      scanf("%d", a[i]+ j);

  memset(dp, -1, sizeof dp);

  for (int i = 0; i < (1<<n); i++)

  {

    int idx = 0;

    for (int j = 0; j < n; j++)

    {

      if (i & (1<<j))arr[idx++] = j;

    }

    value[i] = get_cost(idx);

  }

  printf("%lld\n", solve());

}


// Fastest known solution for this problem:
#include <iostream>

#include <algorithm>

#include <vector>

#include <cassert>



using namespace std;





int main() {



  int N;



  cin >> N;

  vector< vector<long long> > A(N, vector<long long>(N));



  for (auto i=0;i <N; i++)

  for (auto j=0;j <N; j++) cin >> A[i][j];



  vector<long long> F( 1<<17, 0);



  // consider all sub sets of {1..N}

  vector<int> l(16, 0);

  for (long long s = 1; s < (1<<N); s++) {

    l.resize(0);



    auto ss= s;

    int c = 0;

    while(ss != 0) {

      if (ss & 1 ) l.push_back(c);

      ss = ss >> 1;

      c++;

    }



    // for (auto tt=0; tt<l.size(); tt++) 

    // cout << "l" << l[tt] << "  ";

    // cout << endl;

    F[s] = 0;

    for (auto i=0; i < l.size(); i++)

    for (auto j=i+1; j < l.size(); j++) F[s] += A[l[i]][l[j]];



    auto L = l.size();



    for (int j = s; j; j = (j-1)&s) {

      F[s] = max( F[s], F[s^j]+F[j]);

    }



    // cout << endl;

  }





  cout << F[ (1<<N)-1] << endl;



  return 0;

}