[NOI2001]炮兵阵地 题解
题意

我们先来了解一下基本的位运算

于( \(\bigwedge\) ),或 (\(\bigvee\) ) 异或(\(\bigoplus\))
在下面我们用(&)代表于,(|)代表或
一道状压dp题,状压真的太难了,这道题搞了比较久才弄懂,首先这道题我们是怎么想到状压dp的呢?首先看范围m<=10,数据范围m很小,地图上部分为山地,部分为平原,且放置了的地方左右各两格,上下各两格不能放置,就只存在两种状态,能放与不能放,就可以看为二进制的0 1我们可以对每一行进行状压,但是我们可以发现我们放置第i行时的状态是会影响到第i-1行和第i-2行的,那么我们可以算一下时间复杂度O( 1024^3*100 ) 明显过不去,那么怎么办呢?我们可以仅考虑当前行的合法状态,于前后行无关,故可以先预处理出状态出来,处理出来只有不到70种
我们可以定义状态
f[i][j][k]表示第i行状态为k且上一行状态为j的最大方案数
状态转移方程
dp[i+1][k][l]=max(dp[i+1][k][l],dp[i][j][k]+sum[l]) (sum[l]表示状态为l中1的个数)
1.判断是否为山丘
在输入时将山丘设为1,平原设为0,那么判断状态是否合法就是直接将状态st[i]&dat[1]若为1则说明则说明放在山丘上了
2.判断每个状态有没有两个炮兵左右距离在两格之内
这个可以画个图便可知道当
if(!(i&(i<<1)) && !(i&(i<<2)))
返回值为真时就可以放置,也就是说 i&(i<<1)&&i&(i<<2)返回值为0
3.每一列前两行有没有炮兵 i&j,i&k 若不为0则冲突(j为i前一行,k为j前一行)
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=110;
int n,m,dp[maxn][maxn][maxn],dat[maxn],sum[maxn],st[maxn],tot,ans;
int clu(int x){
int tmp=0;
while(x){
tmp+=(x&1);
x>>=1;
}
return tmp;
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i){
for(int j=0;j<m;++j){
char ch=getchar();
while(ch!='P'&&ch!='H') ch=getchar();
if(ch=='H') dat[i]|=(1<<j);
}
}
for(int i=0;i<(1<<m);++i){
if(!(i&i<<1)&&!(i&i<<2)){
st[++tot]=i;
sum[tot]=clu(i);
}
}
for(int i=1;i<=tot;++i){
if(!(st[i]&dat[1])) dp[1][1][i]=sum[i];
}
for(int i=1;i<n;++i){
for(int j=1;j<=tot;++j){
for(int k=1;k<=tot;++k){
if(!(st[j]&st[k])&&dp[i][j][k]){
for(int l=1;l<=tot;++l){
if(!(st[l]&st[j])&&!(st[l]&st[k])&&!(st[l]&dat[i+1])){
dp[i+1][k][l]=max(dp[i+1][k][l],dp[i][j][k]+sum[l]);
}
}
}
}
}
}
for(int i=1;i<=tot;++i){
for(int j=1;j<=tot;++j){
ans=max(ans,dp[n][i][j]);
}
}
printf("%d",ans);
return 0;
}
[NOI2001]炮兵阵地 题解的更多相关文章
- 洛谷P2704 [NOI2001]炮兵阵地题解
题目描述 司令部的将军们打算在\(N * M\)的网格地图上部署他们的炮兵部队.一个\(N * M\)的地图由N行M列组成,地图的每一格可能是山地(用\("H"\) 表示),也可能 ...
- [洛谷P2704] [NOI2001]炮兵阵地
洛谷题目链接:[NOI2001]炮兵阵地 题目描述 司令部的将军们打算在NM的网格地图上部署他们的炮兵部队.一个NM的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示), ...
- C++ 洛谷 P2704 [NOI2001]炮兵阵地
P2704 [NOI2001]炮兵阵地 没学状压DP的看一下 此题意思很简单,如下图,就是十字架上的不能有两个点放炮兵. 在做此题前,先做一下玉米田 玉米田题解 分析: 而m即一行的个数小于等于10, ...
- P2704 [NOI2001]炮兵阵地 (状压DP)
题目: P2704 [NOI2001]炮兵阵地 解析: 和互不侵犯一样 就是多了一格 用\(f[i][j][k]\)表示第i行,上一行状态为\(j\),上上行状态为\(k\)的最多的可以放的炮兵 发现 ...
- 洛谷P2704 [NOI2001]炮兵阵地 [状压DP]
题目传送门 炮兵阵地 题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图 ...
- [Poj1185][Noi2001]炮兵阵地(状压dp)
炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 29476 Accepted: 11411 Descriptio ...
- 【题解】洛谷P2704 [NOI2001] 炮兵阵地(状压DP)
洛谷P2704:https://www.luogu.org/problemnew/show/P2704 思路 这道题一开始以为是什么基于状压的高端算法 没想到只是一道加了一行状态判断的状压DP而已 与 ...
- [NOI2001]炮兵阵地 状压DP
题面: 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图.在每一格平原地形上最多 ...
- 洛谷 P2704 [NOI2001]炮兵阵地
题意简述 给定一张地图,有山地H,平原P,平原可放置炮兵, 炮兵可以攻击沿横向左右各两格,沿纵向上下各两格的区域 求最多放几个炮兵,使他们两两攻击不到 题解思路 枚举第i层,第i - 1层,第i - ...
随机推荐
- 读JDK源码集合部分
以前读过一遍JDK源码的集合部分,读完了一段时间后忘了,直到有一次面试简历上还写着读过JDK集合部分的源码,但面试官让我说说,感觉记得不是很清楚了,回答的也模模糊糊的,哎,老了记性越来越差了,所以再回 ...
- win10教育版激活错误:在运行 Microsoft Windows 非核心版本的计算机上,运行"slui.exe ...”
折腾了一天,最终轻松解决,先启用Software Protection服务,在激活(密钥或者工具都行). PS:但是这样还是无法解决Software Protection自动停止的问题,这个可以参考网 ...
- MyBatis 简介与入门
简介 什么是 MyBatis ? MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.My ...
- Hadoop 系列(八)—— 基于 ZooKeeper 搭建 Hadoop 高可用集群
一.高可用简介 Hadoop 高可用 (High Availability) 分为 HDFS 高可用和 YARN 高可用,两者的实现基本类似,但 HDFS NameNode 对数据存储及其一致性的要求 ...
- linux下安装开发环境
jdk 下载jdk安装包,解压到/usr/java/jdk 配置环境变量: #vi /etc/profile 在该profile文件中最下面添加: JAVA_HOME=/usr/java/jdk1.7 ...
- HDU 4635 (完全图 和 有向图缩点)
题目链接:HDU 4635 题目大意: 给你一个有向图,加有向边,使得这个图是简单有向图.问你最多加多少条有向边. 简单有向图: 1.不存在有向重边. 2.不存在图循环.(注意是不存在 “图” 循环 ...
- Missing artifact XXXXX:jar:1.9.1 解决错误问题
昨天导过来一个maven工程的一个项目,由于自己meven库中有许多现成的jar包,但是还是有一些需要去下载的,配置的是阿里云的镜像,把eclise的预编译给关闭,具体做法为:Project----- ...
- 100天搞定机器学习|Day21 Beautiful Soup
前情回顾 机器学习100天|Day1数据预处理 100天搞定机器学习|Day2简单线性回归分析 100天搞定机器学习|Day3多元线性回归 100天搞定机器学习|Day4-6 逻辑回归 100天搞定机 ...
- 配置Windows Server 2008环境
上一章已经把Windows Server2008操作系统安装完毕,接下来配置一下Windows Server环境.配置网络和共享中心.配置桌面环境.配置用户IE设置.安装Telnet远程工具.配置文件 ...
- 重学计算机组成原理(十一)- 门电路的"千里传音"
人用纸和笔来做运算,都是用十进制,直接用十进制和我们最熟悉的符号不是最简单么? 为什么计算机里我们最终要选择二进制呢? 来看看,计算机在硬件层面究竟是怎么表示二进制的,你就会明白,为什么计算机会选择二 ...