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

#include <string>

#include <cstring>

#include <stdlib.h>

#include <math.h>

#include <algorithm>

#include <vector>

#include <set>

#include <map>

#include <queue>

#include <list>

#include <iterator>

#include <assert.h>

#pragma warning(disable:4996) 



typedef long long ll;

#define MIN(a, b) ((a)>(b)? (b): (a))

#define MAX(a, b) ((a)<(b)? (b): (a))

#define LINF 9223300000000000000

#define INF 2140000000

const long long MOD = 1000000007;

using namespace std;





ll a[16][16];



int main(int argc, char* argv[])

{

    int n;

    scanf("%d", &n);



    int i,j;

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

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

            scanf("%lld", &a[i][j]);

        }

    }



    int mm=(1<<n);

    int z[17];

    vector<ll> dp(mm);

    int k;

    for(k=0; k<mm; k++) {

        int siz=0;

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

            if(k & (1<<i)) z[siz++]=i;

        }



        dp[k]=0;

        for(i=0; i<siz; i++) {

            for(j=i+1; j<siz; j++) {

                dp[k] += a[z[i]][z[j]];

            }

        }

    }



    for(k=0; k<mm; k++) {

        int siz=0;

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

            if(k & (1<<i)) z[siz++]=i;

        }

        ll max=0;

        int MM=(1<<siz);

        for(i=0; i<MM; i++) {

            int tmp0=0;

            for(j=0; j<siz; j++) {

                if(i & (1<<j)) tmp0 |= (1<<z[j]);

            }

            ll val = dp[tmp0]+dp[k^tmp0];

            max = MAX(max, val);

        }

        dp[k] = max;

    }

    printf("%lld\n", dp[mm-1]);



    return 0;

}


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

#include <string>

#include <cstring>

#include <stdlib.h>

#include <math.h>

#include <algorithm>

#include <vector>

#include <set>

#include <map>

#include <queue>

#include <list>

#include <iterator>

#include <assert.h>

#pragma warning(disable:4996) 



typedef long long ll;

#define MIN(a, b) ((a)>(b)? (b): (a))

#define MAX(a, b) ((a)<(b)? (b): (a))

#define LINF 9223300000000000000

#define INF 2140000000

const long long MOD = 1000000007;

using namespace std;





ll a[16][16];

ll dp[1<<16];



int main(int argc, char* argv[])

{

    int n;

    scanf("%d", &n);



    int i,j;

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

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

            scanf("%lld", &a[i][j]);

        }

    }



    int mm=(1<<n);

    int z[17];

    int k;

    for(k=0; k<mm; k++) {

        int siz=0;

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

            if(k & (1<<i)) z[siz++]=i;

        }



        dp[k]=0;

        for(i=0; i<siz; i++) {

            for(j=i+1; j<siz; j++) {

                dp[k] += a[z[i]][z[j]];

            }

        }

    }



    for(k=0; k<mm; k++) {

        int siz=0;

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

            if(k & (1<<i)) z[siz++]=i;

        }

        ll max=0;

        int MM=(1<<siz);

        for(i=0; i<MM; i++) {

            int tmp0=0;

            for(j=0; j<siz; j++) {

                if(i & (1<<j)) tmp0 |= (1<<z[j]);

            }

            ll val = dp[tmp0]+dp[k^tmp0];

            max = MAX(max, val);

        }

        dp[k] = max;

    }

    printf("%lld\n", dp[mm-1]);



    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;

}