对状压的重新学习
dp[i][j] :第i行取j种合法取法所能获取的最大值
a[i][j]:第i行第j种取法的和
dp[i][j] = max(dp[i-1][k] + a[i][j]);
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <set>
#include <cmath>
#define LL long long
#define INF 0x3f3f3f3f
#define MOD 998244353
const int maxn = 1e5 + 5;
using namespace std;
int maps[25][25];
int dp[25][maxn];//第i行选第j种方式所获取的最大值
int state[maxn];
int a[25][maxn];//第i行取第j种方式得到的值
int main(){
int n;
while(cin >> n){
memset(dp, 0, sizeof(dp));
memset(a, 0, sizeof(a));
memset(state, 0, sizeof(state));
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
cin >> maps[i][j];
if(n == 0) {//巨坑
cout << 0 << endl;
continue;
}
int cnt = 0;
for(int i=0; i<(1<<n); i++){
if((i & (i << 1)) == 0){//保证不相邻
state[cnt++] = i;
}
}
for(int i=0; i<n; i++){
for(int j=0; j<cnt; j++){
int sum = 0;
for(int k=0; k<n; k++){
if((state[j] & (1 << k)) != 0)
sum += maps[i][k];
}
a[i][j] = sum;
}
}
for(int i=0; i<cnt; i++) dp[0][i] = a[0][i];
for(int i=1; i<n; i++){//n行
for(int j=0; j<cnt; j++){//所有选择方式
for(int k=0; k<cnt; k++){
if((state[j] & state[k]) != 0) continue;
//if((state[j] & (state[k] << 1)) != 0)continue;
//if((state[j] & (state[k] >> 1)) != 0) continue;
dp[i][j] = max(dp[i][j], a[i][j] + dp[i-1][k]);
}
}
}
int ans = 0;
for(int i=0; i<cnt; i++){
ans = max(ans, dp[n-1][i]);
}
cout << ans << endl;
}
}