题目

原题链接


问题描述


分析

每行所放置的炮兵位置有两个要求:
1.必须置于平原;
2.同行或同列的炮兵距离必须不小于两个方格。

我们借助状态压缩简化过程。
以一个数来表示一行上的炮兵放置情况,化为二进制后,1表示放置,0表示空置。
同样以这个来表示一行上的平原与山地的分布情况,根据要求,平原可放可不放,山地不可放,我们不妨以或运算来简化判断。
以 ( 0110 ) 2 (0110)_2 (0110)2​表示 ( H P P H ) (HPPH) (HPPH),只有 ( 0 x x 0 ) 2 (0xx0)_2 (0xx0)2​的放置才是合法的,两者进行或运算的结果就是 ( 0110 ) 2 (0110)_2 (0110)2​,其余的非法放置均得不到这个值。

我们再处理一下行列矛盾,我们不妨预处理行的合法排布,再对列进行递推。

一行中,不允许发生两者相隔小于等于一格,可以分为两种非法情况:
1.相邻
2.相隔一格
依然可以借助位运算简化判断。
若相邻, ( j < < 1 ) & j (j<<1)\&j (j<<1)&j的值必然至少有一位为 1 1 1,结果非 0 0 0;
若相隔一格, ( j < < 2 ) & j (j<<2)\&j (j<<2)&j的值必然至少有一位为 1 1 1,结果非 0 0 0。

由上,我们可以得到每一行的合法排布的集合,我们将这个值存入向量中,同时可以计算每种排布所需的炮兵总数, j . n u m j.num j.num表示状态 j j j需要的炮兵总数,借助 l o w b i t lowbit lowbit可以快速求出。

在列的讨论中,我一开始以 d p [ i ] [ j ] ( 第 i 行 采 取 状 态 j 时 的 最 大 炮 兵 放 置 数 ) dp[i][j](第i行采取状态j时的最大炮兵放置数) dp[i][j](第i行采取状态j时的最大炮兵放置数),但递推有问题,不足以说明值的合法性。
所以后面换成了 d p [ i ] [ j ] [ k ] ( 第 i 行 采 取 状 态 j , 上 一 行 采 取 状 态 k 是 的 最 大 炮 兵 放 置 数 ) dp[i][j][k](第i行采取状态j,上一行采取状态k是的最大炮兵放置数) dp[i][j][k](第i行采取状态j,上一行采取状态k是的最大炮兵放置数)
那么我们的递推公式就是 d p [ i ] [ j ] [ k ] = m a x ( d p [ i ] [ j ] [ k ] , d p [ i − 1 ] [ k ] [ l ] + j . n u m ) dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+j.num) dp[i][j][k]=max(dp[i][j][k],dp[i−1][k][l]+j.num)。
讨论第 i i i行时,通过三重循环枚举合法情况即可,两者不冲突即在二进制同一位上不均为1,通过与运算可直接判断。

但此时的空间大小为 1 0 8 10^8 108,我们有两种处理思路:
1.采用滚动数组,因为我们观察到之后的递推只涉及三行(下方代码写法);
2.观察法,每一行的合法状态不多,即便一行全是平原,也只有60种可能,使用一个 60 ∗ 60 ∗ 100 60*60*100 60∗60∗100大小的空间就够了,以一个下标来表示一种特定的状态,所以可以对空间进行简化。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define fir(i, a, b) for (int i = (a); i <= (b); i++)
#define rif(i, a, b) for (int i = (a); i >= (b); i--)
const ll N=1e3+5;
const ll mod=1e8;
ll n,m,st[105],dp[1024][1024][5];
struct node{ll State,num;node(){State=num=0;}node(ll x,ll y){State=x;num=y;}
};
vector<node>state[105];
void init(){fir(i,0,n-1){fir(j,0,m-1){char tmp;cin>>tmp;st[i]*=2;if(tmp=='P'||tmp=='p')st[i]+=1;//p均可,h不可 ,低位于右 }   }ll sz=(1<<m)-1;fir(i,0,n-1){fir(j,0,sz){ll tmp=st[i];if((tmp|j)!=tmp)continue;//表示于h放置,不合法if(((j<<1)&j)) continue;//表示有相邻放置,不合法 if(((j<<2)&j)) continue;//表示有相间放置,不合法 tmp=j;ll cnt=0;while(tmp){cnt++;tmp-=tmp&(-tmp);}state[i].push_back({j,cnt});}}
}
int main(){cin>>n>>m;init();ll sz=(1<<m)-1;for(auto x:state[0]){fir(i,0,sz){dp[i][x.State][0]=x.num;}}for(auto x:state[0]){for(auto y:state[1]){if(!(x.State&y.State)){dp[x.State][y.State][1]=x.num+y.num;}}}fir(i,2,n-1){for(auto x:state[i]){for(auto y:state[i-1]){//x的每个位置与y上无冲突 if((x.State&y.State))continue;for(auto z:state[i-2]){//x的每个位置与z上无冲突 ,y的每个位置与z上无冲突 if(x.State&z.State)continue;if(y.State&z.State)continue;dp[y.State][x.State][i%3]=max(dp[y.State][x.State][i%3],x.num+dp[z.State][y.State][(i-1)%3]);}}}}ll ans=0;fir(i,0,sz){fir(j,0,sz){ans=max(ans,dp[i][j][(n-1)%3]);}}cout<<ans;return 0;
}
/*
8 4
HPPH
PPPP
HPPH
PHHP
PHHP
HPPH
PPPP
HPPH85 4
PHPP
PPHH
PPPP
PHPP
PHHP63 4
PHPP
PPHH
PPPP 4  1 1
P1
*/

炮兵阵地(状态压缩DP)相关推荐

  1. POJ 1185 炮兵阵地(状态压缩DP)

    Description 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用&quo ...

  2. 玉米田 炮兵阵地 状态压缩DP

    玉米田 原题 #include <cstring> #include <iostream> #include <algorithm> #include <ve ...

  3. POJ1185炮兵阵地(状态压缩 + dp)

    题目链接 题意:给出一张n * m的地图,其中 有的地方能放大炮,有的地方不能,大炮与上下左右两个单位范围内会相互攻击,问最多能放几个大炮 能放大炮为1不能放大炮为0,把每一行看做一个状态,要除去同一 ...

  4. jzoj1768,P2704,POJ1185-[NOI2001]炮兵阵地【状态压缩dp】

    正题 POJ链接:http://poj.org/problem?id=1185 jzoj链接:https://jzoj.net/senior/#main/show/1768 洛谷评测记录:https: ...

  5. 0x56. 动态规划 - 状态压缩DP(习题详解 × 7)

    目录 Problem A. 最短Hamilton路径 ProblemB. 蒙德里安的梦想 Problem C. Corn Fields Problem D. 小国王 Problem E. 炮兵阵地 P ...

  6. 状态压缩DP AcWing算法提高课 (详解)

    基础课的状态压缩点这里 基础课中 蒙德里安的梦想 属于 棋盘式状态压缩dp,最短Hamilton路径 属于 集合状态压缩dp 1064. 小国王(棋盘式/基于连通性) 这种棋盘放置类问题,在没有事先知 ...

  7. 状态压缩DP(大佬写的很好,转来看)

    奉上大佬博客 https://blog.csdn.net/accry/article/details/6607703 动态规划本来就很抽象,状态的设定和状态的转移都不好把握,而状态压缩的动态规划解决的 ...

  8. 状态压缩dp学习小记part2

    继续学习状态压缩的相关知识. 本来准备继续按照上篇博文里提到的那篇论文继续学习,但被矩形完全覆盖虐了回来,决定先做些其他的题增进理解之后再回来做. Zoj 3471 Most Powerful 题目链 ...

  9. 第一章 动态规划 状态压缩DP

    1.基本概述 状态压缩dp和状态机一样,都是一种特殊的状态表示方式.状态机用一系列小状态表示某一状态.状态压缩dp用二进制数进行表示.虽然看代码起来时间复杂度比较高,但是很多的情况都给剪枝掉了. 状态 ...

  10. 动态规划-状态压缩DP

    [SCOI2005] 互不侵犯 题目描述 https://www.luogu.com.cn/problem/P1896 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它 ...

最新文章

  1. 无法找到“XXX.exe”的调试信息,或者调试信息不匹配。未使用调试信息生成二进制文件...
  2. centos找不到chattr命令_一个骚命令防止你的文件被误删除!
  3. LM3S1138驱动函数SysCtlPeripheralEnable解析
  4. 分布与并行计算—用任务管理器画CPU正弦曲线(Java)
  5. Spring MVC X-Frame-Options
  6. CCIE-LAB-SDN-第六篇-SDWAN-Branch2-vEdge-51-vEdge-52
  7. 剑指offer--面试题13
  8. 转载--#define 用法
  9. 原生js将数组分割成固定个数一组的小数组
  10. Mobile First! Wijmo 5 之 架构
  11. VS2005制作安装包
  12. 什么是4k视频分辨率
  13. 第二证券|扶持政策频发,教育板块再度爆发,全通教育“20cm”涨停
  14. 产品分析报告——“京东到家”
  15. 算法工程师和python_Python工程师与人工智能算法工程师有什么区别?
  16. Java oss 上传图片视频
  17. python 矩阵化为最简阶梯型
  18. App高危漏洞 Android用户记得更新百度全家桶
  19. Flink (四) Flink 的安装和部署- Flink on Yarn 模式 / 集群HA / 并行度和Slot
  20. java实现从url路径中下载pdf文档到本地

热门文章

  1. 引自天天安全网 ——※ 中华民族传统文化精髓___二十四孝 ※
  2. 使用video标签,连续播放无限个mp4(h264封装的)视频时,画面会闪烁的问题解决
  3. 18个扩展让你的Firefox成为渗透测试工具
  4. Vite2.x + Vue3.x + Typescript + Element-plus搭建完整的后台管理系统项目
  5. HBase清空表数据
  6. linux防火墙关闭启用增减端口号命令
  7. linux下端口占用杀死
  8. filder使用方式
  9. pytorch_gru理解
  10. 打包出的unity会黑屏_unity3d 5.0以上打包安卓apk部分手机黑屏问题,尤其魅族手机...