// Original C++ solution (slower):
#include <bits/stdc++.h>



using namespace std;



typedef long long ll;

typedef long double ld;



int n;

ll v[(1 << 16)];

int mat[16][16];

vector<int> m[(1 << 16)];



void get_masks(int idx, int mask, int a)

{

    if(idx == n){

      m[a].push_back(mask);

      return;

    }

    get_masks(idx + 1, mask, a);

    if(mask & (1 << idx))

    {

      get_masks(idx + 1, mask ^ (1 << idx), a);

    }

}



ll dp[(1 << 16)];

bool mark[(1 << 16)];

ll solve(int mask)

{

    if(mask == (1 << n) - 1)

      return 0;

    ll &ans = dp[mask];

    if(mark[mask])

      return ans;

    mark[mask] = 1;

    ans = -1e12;

    for(auto &x: m[mask])

    {

      ans = max(ans, solve(mask | x) + v[x]);

    }

    return ans;

}



int main()

{

    cin >> n;

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

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

        cin >> mat[i][j];

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

    {

      vector<int> p;

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

      {

        if(i & (1 << j))

          p.push_back(j);

      }

      ll val = 0;

      for(int k = 0; k < p.size(); k++)

        for(int z = k + 1; z < p.size(); z++)

          val += mat[p[k]][p[z]];

      int newMask = i;

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

        newMask ^= (1 << j);

      get_masks(0, newMask, i);

      v[i] = val;

    }

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

    cout << solve(0);

}


// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>



using namespace std;



typedef long long ll;



const int N = (1 << 16) + 5;

int arr[16][16];

int n;

ll val[N];

vector<int> m[N];

ll dp[N];



void get_masks(int idx, int mask, int pos)

{

  if(idx == n)

  {

    if(mask)

      m[pos].push_back(mask);

    return;

  }

  get_masks(idx + 1, mask, pos);

  if(mask & (1 << idx))

    get_masks(idx + 1, mask ^ (1 << idx), pos);

}



int main()

{

  cin >> n;

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

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

      cin >> arr[i][j];

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

  {

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

    {

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

      {

        if((i & (1 << j)) && (i & (1 << k)))

          val[i] += arr[j][k];

      }

    }

  }

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

  {

    int newMask = i;

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

      newMask ^= (1 << j);

    get_masks(0, newMask, i);

  }

  for(int i = (1 << n) - 2; i >= 0; i--)

  {

    for(auto &x: m[i])

    {

      dp[i] = max(dp[i], dp[i | x] + val[x]);

    }

  }

  cout << dp[0];

  return 0;

}


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

}