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;
}
相关推荐
choumin1 天前
创建型模式——工厂方法模式
c++·设计模式·工厂方法模式·创建型模式
云小逸1 天前
【SVN 详细使用指南:从入门到团队协作】
c++·svn
徐小夕1 天前
花了一周,3亿tokens,我开源了一款 Word 文档智能审查平台,文稿自动质检+可视化分析,告别低效人工审核
前端·算法·github
可编程芯片开发1 天前
UPFC统一潮流控制器的simulink建模与仿真
算法
小小仙子1 天前
矢量网络分析仪如何测试S参数的?
人工智能·算法·机器学习
中微极客1 天前
降维算法75倍加速:从PCA到稀疏字典学习的工程实践
人工智能·学习·算法
storyseek1 天前
前缀和实现Kogge-Stone算法
数据结构·算法
ziguo11221 天前
深入浅出 C/C++ 数据类型:从入门到踩坑
linux·c语言·c++·windows·visual studio
元Y亨H1 天前
开发者必须掌握的十大核心算法
算法