题目

原题链接


问题描述


分析

每行所放置的炮兵位置有两个要求:
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. 常用的JQuery数字类型验证正则表达式
  2. [转]VC无负担实现XP风格界面
  3. ArcMap 水文分析 部分功能
  4. tensorflow 转张量类型为float_5个简单的步骤掌握Tensorflow的Tensor
  5. 【BZOJ1597】【Tyvj2461】土地购买,第一次的斜率优化DP
  6. 《R in Action》读书笔记(2)
  7. 【OpenCV4】fatal error: opencv2/core.hpp: No such file or directory 解决方法
  8. hlw8012arduino代码_麻雀虽小五脏俱全-liteduino arduino开发板PCB文件
  9. 总结:xshell的一些使用技巧
  10. C++实现进程通信(管道pipe)
  11. android相机拉伸解决办法
  12. 在线运行Java代码获取APNIC中国区的ip段,用作绕过国内ip
  13. 通过跳绳瘦下来是一种怎么样的体验?
  14. 新智慧杂志新智慧杂志社新智慧编辑部2022年第9期目录
  15. 网易企业邮箱管理功能
  16. 第5次作业+160+曾元鹏
  17. Google搜索中国定制版已黄了,百度再次PK的希望或落空
  18. 森林资源保护类毕业论文文献包含哪些?
  19. 怎样识别图片中的文字?手机电脑都可以的
  20. 在Tomcat下部署Jenkins

热门文章

  1. 如何挑选考研政治的复习资料
  2. @Target、@Retention、@Documented元注解简介
  3. 免费PDF转Word?有这几个网站就够了。
  4. JS判断字符串是否为json字符串
  5. ZnSe/ZnS量子点,硒化锌量子点,ZnSe/ZnS QDs(发射波长主要覆盖紫光和蓝光应用于QLED)
  6. Sklearn包含的常用算法
  7. python安卓程序,python软件安卓版
  8. 火山引擎 DataLeap:揭秘字节跳动业务背后的分布式数据治理思路
  9. Pyqt5实践:实现快捷方式软件
  10. mysql 删除slave_如何清除Slave的配置信息