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;
}
相关推荐
s_w.h30 分钟前
【 刷题 】双指针
算法
啥都想学点的研究生34 分钟前
一篇文章讲清楚:K-Means聚类算法
算法·kmeans·聚类
白狐_79844 分钟前
408 数据结构|KMP做题方法:next、nextval和高频易错点
数据结构·算法
月华路1 小时前
《模型不玄学》第20章 两种评估视角
人工智能·算法·机器学习
禹凕1 小时前
快速幂算法详解与实战
python·算法
xxwl5851 小时前
高斯消元法异或版
人工智能·算法·机器学习
sylviiiiiia1 小时前
leetcode hot 100
python·算法·leetcode
励志不掉头发的内向程序员2 小时前
【LibreCAD 2D架构】从鼠标点击到图形创建:RS_ActionDrawLine交互流程与状态机解析
开发语言·c++·qt·学习·系统架构·计算机外设·交互
OPEN-F2 小时前
ROS2系列教程:Gazebo插件(关节控制/IMU/激光雷达)
c++·python·数码相机·算法·机器人
luj_17682 小时前
虚实交融中的真实人物塑造
c语言·开发语言·网络·经验分享·算法