P1123 取数游戏

类似于开关问题的二进制枚举,二进制枚举第一行的情况,那么第二行的选择情况会受到上一行的限制,并且还需要保证本身不存在相邻的数字,这样一直枚举到最后一行比较一下选择数字的和,存一个最大的答案就可以了,复杂度\(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;
}
posted @ 2021-07-19 15:34  yys_c  阅读(65)  评论(0编辑  收藏  举报