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;
}
相关推荐
mmmmath_35 小时前
LeetCode.225.用队列实现栈
算法
Elaine3365 小时前
数据结构与算法-程序
数据结构·python·算法·计算机基础·编程基础
2601_965742225 小时前
布局GEO AI本地营销,我重点看这几个细节
大数据·人工智能·算法·ai·新媒体运营
EatFan5 小时前
AI Agent 上生产前先加三道闸门:审批、限权、可回放的工程实践
人工智能·python·算法·多智能体·ai agent·mcp·harness
思茂信息5 小时前
CST软件BCI仿真模型及仿真案例
开发语言·单片机·嵌入式硬件·算法·emc
海上小飞龙6 小时前
改一个数,右边全得重算,这题怎么扛住两万次查询
java·c++·python
Persistent的粽子!6 小时前
双指针算法:最大盛水容器
c++·算法·leetcode
小小龙学IT6 小时前
三菱 PLC MC 协议(SLMP / QnA 兼容 3E 帧)深度解析:从帧结构到 C++/Go 双语言采集实战
c语言·c++·golang
程序猿编码6 小时前
C++/CUDA 手写 LLM 推理引擎:拆解 vLLM 核心 PagedAttention 与连续批处理
开发语言·c++·深度学习·神经网络·推理·vllm
hold?fish:palm6 小时前
44 二叉搜索树中第K小的元素
开发语言·c++·算法