题目

原题来自:\(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. Mysql的默认最大连接数及如何修改

    一.Mysql默认最大连接数 通过查看mysql安装目录的my.ini文件,发现mysql的默认最大的连接数为100,实际场景中,以及进行压测时,100时远远不够的,一般都会设置最大的连接数. 二.如 ...

  2. ant构建Jmeter脚本的build文件配置(build.xml)

    使用此构建文件可自动发送邮件  代码如下: <?xml version="1.0" encoding="UTF8"?> <project na ...

  3. Spring zuul 快速入门实践 --看zuul如何进行服务转发

    zuul 作为springCloud 的全家桶组件之一,有着不可或缺的分量.它作为一个普通java API网关,自有网关的好处: 避免将内部信息暴露给外部: 统一服务端应用入口: 为微服务添加额外的安 ...

  4. EasyARM-iMX257如何配置出低速率CAN

    EasyARM-iMX257如何配置出低速率CAN 在EasyARM-iMX257 Linux开发指南 V1.02.01"5.6 socket CAN编程socket CAN编程" ...

  5. 05-IntentFilter的匹配规则

    IntentFilter的匹配规则 原则上一个Intent不应该既是显示调用又是隐式调用,如果二者共存的话以显式调用为主 隐式调用需要Intent能够匹配目标组件的IntentFilter中所设置的过 ...

  6. LeetCode 75,90%的人想不出最佳解的简单题

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode专题的44篇文章,我们一起来看下LeetCode的75题,颜色排序 Sort Colors. 这题的官方难度是Medi ...

  7. 【快手初面】要求3个线程按顺序循环执行,如循环打印A,B,C

    [背景]这个题目是当时远程面试时,手写的题目.自己比较惭愧,当时写的并不好,面试完就又好好的完善了下. 一.题意分析 3个线程要按顺序执行,就要通过线程通信去控制这3个线程的执行顺序. 而线程通信的方 ...

  8. 在c++MFC下用PCL显示操作点云文件 MFC对话框显示操作PCL点云

    原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/13115873.html 第一步 下载PCL库  我的版本是1.8.1的 你都要MFC下跑PCL ...

  9. 使用三台云服务器搭建真正的Redis集群

    三台云服务器搭建redis集群# 今天花了一天的时间弄集群redis:遇到了很多坑,从头开始吧 环境讲解: 两台配置:1核2G,另一台:1核1G: 操作系统:Centos 7.6 Redis:3.2. ...

  10. 【Azure SQL】数据库性能分析

    前置条件 用户有查询数据统计权限 GRANT VIEW DATABASE STATE TO database_user; CPU性能问题 正在发生 查看前X个CPU消耗查询 (汇总) SELECT T ...