题目

原题来自:\(NOI 2001\)

司令部的将军们打算在\(N*M\)

的网格地图上部署他们的炮兵部队。一个\(N*M\)的地图由\(N\)行\(M\)列组成,地图的每一格可能是山地(用 H表示),也可能是平原(用 P 表示)。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队),如果在地图中的灰色所标识的平原上部署一支炮兵部队,它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。其他位置攻击不到。炮兵的攻击范围不受地形的影响。现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。

输入格式

第一行包含两个由空格分割开的正整数,分别表示\(N\)和\(M\);

接下来的\(N\)行,每一行含有连续的\(M\)个字符(P 或者 H),中间没有空格。按顺序表示地图中每一行的数据。

输出格式

仅一行,包含一个整数\(K\),表示最多能摆放的炮兵部队的数量。

样例

样例输入

5 4

PHPP

PPHH

PPPP

PHPP

PHHP

样例输出

6

思路

这道题是一个很有趣的状压DP,由题意可知,对当前状态影响的有当前行状态,上一行状态,以及上上行的状态,对该行都有影响,所以,很显然我们枚举第\(i\)行,\(i-1\)行以及\(i-2\)的状态,对于任意一行(假设为\(i\)),那么我们对第\(i\)行进行合法化判断(仅对当前行),记录合法状态以及数目,方便下面枚举,还需要注意的是地图上的山地,需要单独开一个数组记录,与枚举状态求&,然后我们设\(F\)的三维数组,即\(F[i][j][k]\)代表第i行第j种状态从上一行第k种状态转移过来的最优解,所以有\(f[i][w][k]=max(f[i][w][k],f[i-1][k][j]+Q(w))\),\(f[i][w][k]\)上一状态为\(f[i-1][k][j]\),继承或求较大值更新

如果还是不明白的话,代码奉上



#include<bits/stdc++.h>
using namespace std;
const int maxn=1<<9;
int f[100+10][maxn][maxn];//第i行第j种状态从上一行第k种状态转移过来的最优解
int a[100+10];//记录地图山丘的数量
int state[maxn];//记录合法的状态
int tot,n,m;
int lowbit(int x){//求最低位1
return x&-x;
}
int Q(int x){//判断第x种合法状态下的炮兵个数
x=state[x];
int cnt=0;
for(int i=x;i;i-=lowbit(i))cnt++;
return cnt; } bool judge(int x){//判断状态x的合法性
if(x&(x<<1) || x&(x<<2))return 0;
return 1;
}
int main(){ cin>>n>>m;
char ch;
for(int i=1;i<=n;i++){
for(int j=0;j<m;j++){
scanf(" %c ",&ch);
if(ch=='H')a[i]+=(1<<j);//记录山丘位置
}
}
for(int i=0;i<(1<<m);i++){//记录合法状态
if(judge(i))state[++tot]=i;
}
for(int i=1;i<=tot;i++){//初始化第一行i种状态下的最优解,即为当前状态下的炮兵数量
if((a[1] & state[i])==0)f[1][i][1]=Q(i);
}
for(int i=2;i<=n;i++){//枚举第i行
for(int j=1;j<=tot;j++){//i-2行
if(state[j] & a[i-2])continue;//判断第i-2行
for(int k=1;k<=tot;k++){//枚举第i-1行
if(state[k] & a[i-1])continue;//判断第i-1行
if(state[k] & state[j])continue;//判断第i-1行与第i-2行
for(int w=1;w<=tot;w++){
if(state[w] & a[i])continue;//判断第i行
if(state[w] & state[k])continue;//判断第i行和第i-1行
if(state[w] & state[j])continue;//判断第i行和第i-2行
f[i][w][k]=max(f[i][w][k],f[i-1][k][j]+Q(w));//合法情况转移
}
}
}
}
int ans=0;
for(int i=1;i<=tot;i++){//求解
for(int j=1;j<=tot;j++){
if(a[n-1] & state[i])continue;
if(a[n] & state[j])continue;
if(state[i] & state[j])continue;
ans=max(f[n][j][i],ans);
}
}
cout<<ans<<endl; }

状压DP之炮兵阵地的更多相关文章

  1. dp乱写1:状态压缩dp(状压dp)炮兵阵地

    https://www.luogu.org/problem/show?pid=2704 题意: 炮兵在地图上的摆放位子只能在平地('P') 炮兵可以攻击上下左右各两格的格子: 而高原('H')上炮兵能 ...

  2. [状压dp]POJ1185 炮兵阵地

    中文题 题意不再赘述 对于中间这个“P” 根据dp的无后效性 我们只需考虑前面的 就变成了 只需考虑: 也就是状压前两行 具体与HDOJ的4539类似: 看HDOJ 4539 仅仅是共存状态的判断不同 ...

  3. 状压DP初识~~炮兵阵地

    炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 31718   Accepted: 12253 Descriptio ...

  4. POJ 1185 炮兵阵地(状压DP)

    炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 26426   Accepted: 10185 Descriptio ...

  5. [poj1185]炮兵阵地_状压dp

    炮兵阵地 poj-1185 题目大意:给出n列m行,在其中添加炮兵,问最多能加的炮兵数. 注释:n<=100,m<=10.然后只能在平原的地方建立炮兵. 想法:第2到状压dp,++.这题显 ...

  6. TZOJ 4912 炮兵阵地(状压dp)

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

  7. POJ P1185 炮兵阵地 【状压dp】

    炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 29502 Accepted: 11424 Description 司令 ...

  8. 洛谷P2704 [NOI2001]炮兵阵地 [状压DP]

    题目传送门 炮兵阵地 题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图 ...

  9. POJ1185 炮兵阵地 —— 状压DP

    题目链接:http://poj.org/problem?id=1185 炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions ...

随机推荐

  1. Linux文件处理命令 ls 详解

    Linux系统的应用场景最多的就是用作服务器的系统了,简洁,安全,高效,一般我们服务器端不会安装Linux的图形化界面,虽然现在一些Linux发行版的图形界面也很漂亮,但是,服务器最主要的是高效.所以 ...

  2. elementUI+国际化

    1. 先创建一个lang 文件夹,创建两个js文件en.js(英文), zh.js(中文), 另外创建一个index.js文件(用于) en.js zh.js (两者必须保持一致) 2. 在index ...

  3. 在Asp.NET Core中如何优雅的管理用户机密数据

    在Asp.NET Core中如何优雅的管理用户机密数据 背景 回顾 在软件开发过程中,使用配置文件来管理某些对应用程序运行中需要使用的参数是常见的作法.在早期VB/VB.NET时代,经常使用.ini文 ...

  4. SuperSlide之属性targetCell介绍

    禁用页面菜单js代码: <script type="text/javascript"> document.oncontextmenu=function(){ retur ...

  5. 在SpringMVC获取客户端传递的数据的方式

    在处理请求的方法中,加入相对应的形参,保证形参参数名和传递的数据的参数名保持一致,就能够自动赋值 value:当不满足赋值条件时,可以使用value属性,指定映射关系 required:设置形参是否必 ...

  6. 2019-02-03 线性表的顺序储存结构C语言实现

    #include<cstdio> #define MAXSIZE 20 typedef int Elemtype; //Elemtype类型根据实际情况而定,这里取int typedef ...

  7. LR脚本信息函数-lr_get_master_host_name

    lr_get_master_host_name() 返回Controller主机的名称. char * lr_get_master_host_name(); lr_get_master_host_na ...

  8. php读取富文本处理html标签问题

    thinkphp的一项配置会将富文本编辑器的内容中的html标签进行转义处理 'DEFAULT_FILTER' => 'htmlspecialchars', // 默认参数过滤方法使用htmls ...

  9. Redis 数据结构 之 SDS

    SDS(simple dynamic string),简单动态字符串.s同时它被称为 Hacking String.hack 的地方就在 sds 保存了字符串的长度以及剩余空间.sds 的实现在 sd ...

  10. C#数据结构与算法系列(十):逆波兰计算器——逆波兰表达式(后缀表达式)

    1.介绍 后缀表达式又称逆波兰表达式,与前缀表达式相似,只是运算符位于操作数之后 2.举例说明 (3+4)*5-6对应的后缀表达式就是3 4 +5 * 6 - 3.示例 输入一个逆波兰表达式(后缀表达 ...