[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 - ...
随机推荐
- cesium学习——cesium中的坐标
一.坐标展现形式 在cesium中,对于坐标数值单位有三种:角度.弧度和坐标值 1.角度 角度就是我们所熟悉的经纬度,对于地球的坐标建立如下: 图中以本初子午线作为x和z的面,建立了一个空间坐标系.可 ...
- Storm初识(1)
在Storm集群中,有两类节点:主节点 master node 和工作节点 worker nodes. 主节点运行着一个叫做Nimbus的守护进程.这个守护进程负责在集群中分发代码,为工作节点分配任务 ...
- Linux lsof工具介绍
引言 在<Linux fuser工具介绍>一文中,与大家一起学习了fuser工具的使用方法."lsof"——list open files,lsof也是Linux下用于 ...
- SpringBoot电商项目实战 — Redis实现分布式锁
最近有小伙伴发消息说,在Springboot系列文第二篇,zookeeper是不是漏掉了?关于这个问题,其实我在写第二篇的时候已经考虑过,但基于本次系列文章是实战练习,在项目里你能看到Zookeepe ...
- 一个接口多个实现类的Spring注入方式
1. 首先, Interface1 接口有两个实现类 Interface1Impl1 和 Interface1Impl2 Interface1 接口: package com.example.serv ...
- vue-cli3 按需引入element-ui
按照官网的教程:按需引入需要借助:babel-plugin-component 安装:babel-plugin-component 注意:官网是修改 .babelrc 文件,我这里为了方便就直接修改 ...
- bi-Lstm +CRF 实现命名实体标注
1. https://blog.csdn.net/buppt/article/details/82227030 (Bilstm+crf中的crf详解,包括是整体架构) 2. 邹博关于CRF的讲解视频 ...
- Oracle笔记_查询
1 单条件查询 select -- from -- where 条件 -- = > >= < <= != <> -- 单引号用于数据表示字符串 -- 双引号用于数据 ...
- JAVA通过HTTP方式获取数据
测试获取免费天气数据接口:http://www.weather.com.cn/data/sk/101190408.html URL数据如下图: 代码部分: package https; import ...
- 随笔编号-16 JAVA知识框架
基于 J2EE 列举的知识架构,大体列举开发基础知识.帮助我随时查缺补漏,奉行好记性不如烂笔头.写了这该随笔,以便后续查询. 1 JAVA简介 2 JAVA编程环境 3 JAVA基本编程结构 4 ...