top1编程
← 返回题目
题解

炸弹人

1 条题解

  • 0
    @ 2026-7-29 0:19:59
    #include <bits/stdc++.h>
    using namespace std;
    
    int n, m, g[105], dp[105][100][100];
    vector<int> s; // 保存每一行合法的状态
    
    void init_state() { // 预处理出每一行合法的状态
        for(int i = 0; i < (1 << m); ++i) {
            if(i & (i >> 1) || i & (i >> 2)) continue;
            s.push_back(i);
        }
    }
    
    bool check(int x) {
        return x & (x >> 1); // 同一行有相邻的1
    }
    
    int get_cnt(int x, int sta) { // 第x行状态为sta时可以波及到的方格数量
        int ans = 0, flag = 0;
        for(int i = 0; i < m; ++i) {
            if((sta >> i) & 1) {
                flag = 1;
                if(x - 1 >= 1) ++ans;
                if(x + 1 <= n) ++ans;
                if(i - 1 >= 0) ++ans;
                if(i + 1 < m) ++ans;
            }
        }
        return ans + flag;
    }
    
    int main() {
        cin>>n>>m;
        for(int i = 1; i <= n; ++i) { // 处理出每一行的状态g[i]
            for(int j = 1; j <= m; ++j) {
                char ch;
                cin>>ch;
                if(ch == 'A') g[i] = (g[i] << 1) + 1;
                else g[i] = (g[i] << 1) + 0;
            }
        }
        init_state(); // 筛选每行合法的状态
        dp[0][0][0] = 0;
        for(int i = 1; i <= n + 2; ++i) {
            for(int j = 0; j < s.size(); ++j) { // 第i行状态
                for(int k = 0; k < s.size(); ++k) { // 第i-1行状态
                    for(int u = 0; u < s.size(); ++u) { // 第i-2行状态
                        int a = s[u], b = s[k], c = s[j];
                        if(a & b || b & c || a & c) continue;
                        if(g[i] & c || g[i - 1] & b) continue;
                        if(check(b | c)) continue; // 左上与右上
                        int cnt = 0; // 第i行状态波及到的炸弹数
                        if(i <= n) cnt = get_cnt(i, c);
                        dp[i][j][k] = max(dp[i][j][k], dp[i - 1][k][u] + cnt);
                    }
                }
            }
        }
        cout<<dp[n + 2][0][0];
        return 0;
    }
    
    • 1