类似于开关问题的二进制枚举,二进制枚举第一行的情况,那么第二行的选择情况会受到上一行的限制,并且还需要保证本身不存在相邻的数字,这样一直枚举到最后一行比较一下选择数字的和,存一个最大的答案就可以了,复杂度(O(2^mn))
#include<iostream>
using namespace std;
const int N = 6;
int g[N][N];
int st[(1 << N) - 1];
int n, m;
int T;
int ans = -1;
int check(int a, int b){
for(int i = 0; i < m; i ++)
if(a >> i & 1)
if(b >> i + 1 & 1 || b >> i & 1 || i && b >> i - 1 & 1)
return 0;
return 1;
}
void dfs(int u, int v, int sum){
if(u == n){
ans = max(ans, sum);
return;
}
for(int i = 0; i < 1 << m; i ++){
if(!st[i] && check(i, v)){
int t = 0;
for(int j = 0; j < m; j ++)
if(i >> j & 1) t += g[u][j];
dfs(u + 1, i, sum + t);
}
}
}
int main(){
cin >> T;
for(int i = 0; i < 1 << N; i ++)
for(int j = 1; j < N; j ++)
if(i >> j & 1 && (i >> j - 1) & 1)
st[i] = 1;
while(T --){
cin >> n >> m;
for(int i = 0; i < n; i ++)
for(int j = 0; j < m; j ++)
cin >> g[i][j];
ans = -1;
dfs(0, 0, 0);
cout << ans << endl;
}
return 0;
}