Luogu P2704 [NOI2001] 炮兵阵地

P2704 NOI2001 炮兵阵地

思路

对于一行炮兵的分布,会产生影响的只有该行的地形以及前两行的炮兵分布。所以,我们可以使用状压DP,压缩前两行的分布讨论本行。

对于一行,我们可以预先处理出合法的分布,如果不做这一步,时间复杂度会过大。

正解

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

const int N = 105;
const int M = 15;

int n, m;
char ch[N][M];
int a[N];
int dp[N][1<<10][1<<10];

vector<int> mask[N];

inline bool check(int x) {
    vector<int> res;
    for(int i = m - 1; i >= 0; i--) {
        if(x >= (1 << i)) {
            res.push_back(m - i);
            x -= (1 << i);
        }
    }
    if(res.size() == 0) return true;
    for(int i = 0; i < res.size() - 1; i++) {
        if(res[i] + 2 >= res[i + 1]) 
            return false;
    }
    return true;
}

int main() {
    cin>>n>>m;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++) {
            cin>>ch[i][j];
            a[i] <<= 1;
            if(ch[i][j] == 'H') a[i] += 1;
        }
    for(int i = 1; i <= n; i++)
        for(int S = 0; S < (1 << m); S++)
            if(!(S & a[i]) && check(S)) {
                mask[i].push_back(S);
            }
    if(n == 1) {
        int maxn = 0;
        for(int i : mask[1])
            maxn = max(maxn, __builtin_popcount(i));
        cout<<maxn;
        return 0;
    }
    for(int i : mask[2]) {
        for(int j : mask[1])
            if(!(i & j)) {
                dp[2][i][j] = max(dp[2][i][j], __builtin_popcount(i) + __builtin_popcount(j));
        }
    }
    for(int i = 3; i <= n; i++) {
        for(int S1 : mask[i]) {
            for(int S2 : mask[i - 1]) {
                if(S1 & S2) continue;
                    for(int S3 : mask[i - 2]) {
                        if((S1 & S3) || (S2 & S3)) continue;
                        dp[i][S1][S2] = max(dp[i][S1][S2], dp[i-1][S2][S3] + __builtin_popcount(S1));
                    }
            }
        }
    }
    int ans = 0;
    for(int S1 : mask[n]) {
        for(int S2 : mask[n - 1]) {
            if((S2 & a[n - 1]) || !check(S2) || (S1 & S2)) continue;
            ans = max(ans, dp[n][S1][S2]);
        }
    }
    cout<<ans;
    return 0;
}
相关推荐
艾莉丝努力练剑1 分钟前
【AI大模型接入SDK】ChatServer接口实现
c++·人工智能·学习·ai·架构·大模型·sdk
有同事要进步2 分钟前
Leecode第68题:x的平方根
java·数据结构·算法
要练八块腹肌6 分钟前
AVL树的讲解与实现
c++
吹什么轩9 分钟前
linux系统复习:进程优先级与O(1)调度
java·linux·算法
开开心心就好20 分钟前
安卓PDF处理工具,免费无广告零弹窗
android·服务器·开发语言·算法·pdf·ocr
白杨尚青2 小时前
C++进阶篇(二):多态——虚函数、重写、虚函数表与三个经典坑(附完整代码仓库)
开发语言·c++·多态·虚函数·重写·动态绑定
syagain_zsx2 小时前
spdlog实战:日志分级、滚动与性能调优
linux·c++·日志库·二次开发日志库
zyl76516 小时前
FlashAttention 详解:从 GPU 硬件、普通 Attention 到分块计算与 Online Softmax
算法
爱读书的小胖20 小时前
LeetCode 122:买卖股票的最佳时机 II(C)解题分析
算法
结局无敌20 小时前
React Native for OpenHarmony 实战:三方库 react-native-modal-dialog 的鸿蒙化适配指南
深度学习·算法·react native·react.js·harmonyos