Buggy python submission (verdict: Time Limit Exceeded):
import sys
sys.setrecursionlimit(2147483647)
INF = 1 << 60
MOD = 10**9 + 7 # 998244353
input = lambda:sys.stdin.readline().rstrip()
from functools import lru_cache

@lru_cache(None)
def subsets(U): # O(k * 2^k)
    bits = []
    for i in range(U.bit_length()):
        if (U >> i) & 1:
            bits.append(i)
    k = len(bits)
    res = [None] * (1 << k)
    for use in range(1 << k):
        V = 0
        for i in range(k):
            if (use >> i) & 1:
                V |= 1 << bits[i]
        res[use] = V
    return res

def resolve():
    n = int(input())
    A = tuple(tuple(map(int, input().split())) for _ in range(n))

    # O(n^2 * 2^n)
    state_to_score = [0] * (1 << n)
    for U in range(1 << n):
        for i in range(n):
            if (U >> i) & 1 == 0:
                continue
            for j in range(i):
                if (U >> j) & 1:
                    state_to_score[U] += A[i][j]

    # dp[i][U] : i まで見て U <= {1, ..., n} を grouping したときの max
    # msb(U) = i ならば dp[i][U] = dp[i + 1][U] = ... = dp[n - 1][U] なので dp は使いまわせる
    # dp[i + 1][U | 1 << (i + 1)] = max((V + {i + 1} の score) + dp[i][W]) for all V + W = U
    dp = [-INF] * (1 << n)
    dp[0] = 0
    for i in range(n): # 既に U = 0, ..., 2^i - 1 までは確定している
        for U in range(1 << i): # O(2^i) これから 2^i, ..., 2^(i + 1) - 1 を確定させる
            for V in subsets(U): # O(k * 2^k) where k = popcount(U)
                W = U ^ V
                dp[U | 1 << i] = max(dp[U | 1 << i], state_to_score[V | 1 << i] + dp[W])

    print(dp[-1])
resolve()

Fixed submission:
import sys
sys.setrecursionlimit(2147483647)
INF=float("inf")
MOD=10**9+7
input=lambda :sys.stdin.readline().rstrip()
def resolve():
    n=int(input())
    A=[list(map(int,input().split())) for _ in range(n)]
    N=1<<n
    cost=[0]*N
    for mask in range(N):
        for j in range(n):
            for i in range(j):
                if((mask>>i)&1 and (mask>>j)&1):
                    cost[mask]+=A[i][j]
    dp=[-INF]*N
    dp[0]=0
    for mask in range(1,N):
        mask2=mask
        while(mask2):
            tmp=dp[mask&~mask2]+cost[mask2]
            dp[mask]=max(dp[mask],tmp)
            mask2=(mask2-1)&mask
    print(dp[-1])
resolve()

Buggy python submission (verdict: Time Limit Exceeded):
import sys
sys.setrecursionlimit(2147483647)
INF = 1 << 60
MOD = 10**9 + 7 # 998244353
input = lambda:sys.stdin.readline().rstrip()

def subsets(U): # O(n + k * 2^k)
    bits = []
    for i in range(U.bit_length()):
        if (U >> i) & 1:
            bits.append(i)
    k = len(bits)
    res = [None] * (1 << k)
    for use in range(1 << k):
        V = 0
        for i in range(k):
            if (use >> i) & 1:
                V |= 1 << bits[i]
        res[use] = V
    return res

def resolve():
    n = int(input())
    A = tuple(tuple(map(int, input().split())) for _ in range(n))

    # O(n^2 * 2^n)
    state_to_score = [0] * (1 << n)
    for U in range(1 << n):
        for i in range(n):
            if (U >> i) & 1 == 0:
                continue
            for j in range(i):
                if (U >> j) & 1:
                    state_to_score[U] += A[i][j]

    # dp[i][U] : i まで見て U <= {1, ..., n} を grouping したときの max
    # msb(U) = i ならば dp[i][U] = dp[i + 1][U] = ... = dp[n - 1][U] なので dp は使いまわせる
    # dp[i + 1][U | 1 << (i + 1)] = max((V + {i + 1} の score) + dp[i][W]) for all V + W = U
    dp = [-INF] * (1 << n)
    dp[0] = 0
    for i in range(n): # 既に U = 0, ..., 2^i - 1 までは確定している
        for U in range(1 << i): # これから 2^i, ..., 2^(i + 1) - 1 を確定させる
            for V in subsets(U):
                W = U ^ V
                dp[U | 1 << i] = max(dp[U | 1 << i], state_to_score[V | 1 << i] + dp[W])

    print(dp[-1])
resolve()

Fixed submission:
import sys
sys.setrecursionlimit(2147483647)
INF=float("inf")
MOD=10**9+7
input=lambda :sys.stdin.readline().rstrip()
def resolve():
    n=int(input())
    A=[list(map(int,input().split())) for _ in range(n)]
    N=1<<n
    cost=[0]*N
    for mask in range(N):
        for j in range(n):
            for i in range(j):
                if((mask>>i)&1 and (mask>>j)&1):
                    cost[mask]+=A[i][j]
    dp=[-INF]*N
    dp[0]=0
    for mask in range(1,N):
        mask2=mask
        while(mask2):
            tmp=dp[mask&~mask2]+cost[mask2]
            dp[mask]=max(dp[mask],tmp)
            mask2=(mask2-1)&mask
    print(dp[-1])
resolve()