状压DP之炮兵阵地
题目
原题来自:\(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之炮兵阵地的更多相关文章
- dp乱写1:状态压缩dp(状压dp)炮兵阵地
https://www.luogu.org/problem/show?pid=2704 题意: 炮兵在地图上的摆放位子只能在平地('P') 炮兵可以攻击上下左右各两格的格子: 而高原('H')上炮兵能 ...
- [状压dp]POJ1185 炮兵阵地
中文题 题意不再赘述 对于中间这个“P” 根据dp的无后效性 我们只需考虑前面的 就变成了 只需考虑: 也就是状压前两行 具体与HDOJ的4539类似: 看HDOJ 4539 仅仅是共存状态的判断不同 ...
- 状压DP初识~~炮兵阵地
炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 31718 Accepted: 12253 Descriptio ...
- POJ 1185 炮兵阵地(状压DP)
炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 26426 Accepted: 10185 Descriptio ...
- [poj1185]炮兵阵地_状压dp
炮兵阵地 poj-1185 题目大意:给出n列m行,在其中添加炮兵,问最多能加的炮兵数. 注释:n<=100,m<=10.然后只能在平原的地方建立炮兵. 想法:第2到状压dp,++.这题显 ...
- TZOJ 4912 炮兵阵地(状压dp)
描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P" ...
- POJ P1185 炮兵阵地 【状压dp】
炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 29502 Accepted: 11424 Description 司令 ...
- 洛谷P2704 [NOI2001]炮兵阵地 [状压DP]
题目传送门 炮兵阵地 题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图 ...
- POJ1185 炮兵阵地 —— 状压DP
题目链接:http://poj.org/problem?id=1185 炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions ...
随机推荐
- Jmeter加密函数__digest总结
__digest可对多个字符串拼接起来后进行加密,支持多种加密方式,如MD5.MD2.SHA-1.SHA-224.SHA-256.SHA-384.SHA-512. 使用起来非常方便. (注:Jmete ...
- Java培训Day01——制作疫情地图(一)
一.前言 此次培训,是为期三天的网上培训.最终的目的是制作出疫情地图.首先我们来看看主要的讲课内容大纲. Day1 |-Java语法学习(个人感觉讲得还可以,主要围绕本次培训作出的讲解,没有像网上的基 ...
- 02-Python基础1
本节内容 列表.元组操作 字符串操作 字典操作 集合操作 文件操作 字符编码与转码 1. 列表.元组操作 列表是我们最以后最常用的数据类型之一,通过列表可以对数据实现最方便的存储.修改等操作 定义列表 ...
- Hexo博客框架攻略
前言 前天无意在b站看到up主CodeSheep上传的博客搭建教程,引起了我这个有需求但苦于没学过什么博客框架的小白的兴趣.于是花了两天时间终于终于把自己的博客搭建好了,踩了无数的坑,走偏了无数的路, ...
- pip未找到
命令终端运行 sudo easy_install pip 安装成功后最后会显示 Installed /Library/Python/2.7/site-packages/pip-9.0.1-py2.7. ...
- Python itchat.get_chatrooms() 抓取群聊不全的问题
1 rooms = itchat.get_chatrooms() 2 f = codecs.open("3.txt","w","utf-8" ...
- GitHub如何回滚代码?
1.git log 查看commit hash值 执行git log:查看commit hash值. 2.执行git reset --hard xxxx xxxx表示的是commit hash 值. ...
- pomelo 依赖分析
最新版本: 2.2.7 npm i pomelo 之后: ➜ haloServer npm i pomelonpm WARN deprecated node-uuid@1.4.0: Use uuid ...
- WeChair项目Beta冲刺(7/10)
团队项目进行情况 1.昨日进展 Beta冲刺第七天 昨日进展: 前后端并行开发,项目按照计划有条不絮进行 2.今日安排 前端:扫码占座功能和预约功能并行开发 后端:扫码占座后端逻辑开发,编码预约 ...
- 如何解决jeecgBoot前端运行项目之后无法获取验证码的问题
我也是第一次接触这个开源项目,拿到项目之后,安装完环境和依赖,当我启动项目的时候,验证码却刷新不出来. 然后公司后端告诉我需要改两个接口,一个是public目录下的index.html和vue.con ...