洛谷2704 [NOI2001]炮兵阵地
题目戳这里
Solution
状压DP很好的入门题,用熟练位运算貌似也没那么难。
首先分析一下题目:
看见n=100,m=10,立马就想到了状压,看起来也像DP,所以我们还是采用行号为阶段的状压DP。
因为每个炮兵可以攻击到上面两行的范围,所以枚举i行状态时需要知道i-1和i-2行的状态。我们把每一行的状态看成一个M位的二进制数,第p位为1代表该行第p列放置了一个炮兵,0代表没有。
在DP前,我们先预处理出集合S,代表“相邻两个1的距离不小于3”的所有M位二进制数,g数组储存对应S集合中某个数含有的1的个数。然后还需要预处理出1行和2行状态。
那么状态定义也很明显了,f[j][k][i]表示第i行状态为j,第i-1行状态为k的方案数,那么只需枚举上一行状态和上两行状态便可以转移。
虽然M为的二进制数有\(2^M\)个,但是我们只枚举S集合里面的数(其他的不合法),所以时间复杂度为\(O(N|S|^2)\),事实上S集合非常小。
Coding
#include<bits/stdc++.h>
using namespace std;
const int N = 105;
int num,S[N*20],ans,n,m,f[N*20][N*20][101],sum[N*20],a[N],g[N];
int count(int x)
{
int num=0;
while(x)
{
if(x%2==1) num++;
x/=2;
}
return num;
}
int main()
{
char x;
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=0;j<m;j++)
{ cin>>x; if(x=='H') a[i]+=1<<j;}
for(int i=0;i<(1<<m);i++)//预处理S集合
if(((i&(i<<1))==0)&&((i&(i<<2))==0)&&((i&(i>>1))==0)&&((i&(i>>2))==0))
{
S[++num]=i;
g[num]=count(i);
if((i&a[1])==0) f[0][num][1]=g[num];
}
for(int i=1;i<=num;i++)//预处理前两行
for(int j=1;j<=num;j++)
if(((S[i]&S[j])==0)&&((S[j]&a[2])==0)) f[i][j][2]=max(f[i][j][2],f[0][i][1]+g[j]);
for(int i=3;i<=n;i++)
for(int j=1;j<=num;j++)
if((a[i]&S[j])==0)
for(int k=1;k<=num;k++)
if((S[k]&S[j])==0)
for(int last=1;last<=num;last++)
if(((S[last]&S[k])==0)&&((S[last]&S[j])==0)) f[k][j][i]=max(f[k][j][i],f[last][k][i-1]+g[j]);
for(int i=1;i<=num;i++)
for(int j=1;j<=num;j++)
ans=max(ans,f[i][j][n]);
cout<<ans;
return 0;
}
洛谷2704 [NOI2001]炮兵阵地的更多相关文章
- [洛谷P2704] [NOI2001]炮兵阵地
洛谷题目链接:[NOI2001]炮兵阵地 题目描述 司令部的将军们打算在NM的网格地图上部署他们的炮兵部队.一个NM的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示), ...
- C++ 洛谷 P2704 [NOI2001]炮兵阵地
P2704 [NOI2001]炮兵阵地 没学状压DP的看一下 此题意思很简单,如下图,就是十字架上的不能有两个点放炮兵. 在做此题前,先做一下玉米田 玉米田题解 分析: 而m即一行的个数小于等于10, ...
- 洛谷P2704 [NOI2001]炮兵阵地 [状压DP]
题目传送门 炮兵阵地 题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图 ...
- 【题解】洛谷P2704 [NOI2001] 炮兵阵地(状压DP)
洛谷P2704:https://www.luogu.org/problemnew/show/P2704 思路 这道题一开始以为是什么基于状压的高端算法 没想到只是一道加了一行状态判断的状压DP而已 与 ...
- 洛谷 P2704 [NOI2001]炮兵阵地
题意简述 给定一张地图,有山地H,平原P,平原可放置炮兵, 炮兵可以攻击沿横向左右各两格,沿纵向上下各两格的区域 求最多放几个炮兵,使他们两两攻击不到 题解思路 枚举第i层,第i - 1层,第i - ...
- 洛谷P2704 [NOI2001]炮兵阵地题解
题目描述 司令部的将军们打算在\(N * M\)的网格地图上部署他们的炮兵部队.一个\(N * M\)的地图由N行M列组成,地图的每一格可能是山地(用\("H"\) 表示),也可能 ...
- 洛谷 P2704 [NOI2001]炮兵阵地 (状态压缩DP+优化)
题目描述 司令部的将军们打算在NM的网格地图上部署他们的炮兵部队.一个NM的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P" ...
- 【洛谷P2704】炮兵阵地
题目大意:定义一个炮兵会影响该点所在坐标上下左右两个格子的范围,求一个 N*M 的网格里最多可以放多少个炮兵. 题解:发现这个问题有需要记录两个状态,即:上一层的状态和上两层的状态,若直接进行记录,空 ...
- Luogu 2704 [NOI2001]炮兵阵地
唔,想到了状压之后就不会了……实在是菜 考虑压两行,设$f_{i, j, k}$表示当前到第$i$行,上一行是$j$状态,前一行是$k$状态的最多能放的炮兵的数量. 发现第一维还可以滚掉,好像可以转移 ...
随机推荐
- 2017.9.15 postgresql批量插入造成冲突后执行更新
参考来自:https://stackoverflow.com/questions/40647600/postgresql-multi-value-upserts/46233907#46233907 1 ...
- Oracle基础 索引
一.索引 索引是一种快速访问数据的途径,可提高数据库性能.索引使数据库程序无须对整个表进行扫描,就可以在其中找到所需的数据,就像书的目录,可以快速查找所需的信息,无须阅读整本书. (一)索引的分类 逻 ...
- C++Singleton的DCLP(双重锁)实现以及性能测评
本文系原创,转载请注明:http://www.cnblogs.com/inevermore/p/4014577.html 根据维基百科,对单例模式的描述是: 确保一个类只有一个实例,并提供对该 ...
- ddmrp
DDMRP 特点 在供应链加入 mts 缓冲,解耦 lead time, 缩小 bullwhip 效应,最小化库存 buffer动态调整 buffer 分3个颜色共 4个区域[zone],为 gree ...
- 约瑟夫环用php实现
百度百科的解释:约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数 ...
- Godaddy域名 绑定ip 服务器
比如我的域名是wmxl.info 第一个红框代表wmxl.info 绑定的 211.83.110.216 第一个代表www.wmxl.info 绑定的 211.83.110.216, 你也可以换一个服 ...
- java之CGLIB动态代理
© 版权声明:本文为博主原创文章,转载请注明出处 CGLIB动态代理: CGLIB动态代理就是对指定的类生成一个子类,覆盖其中所有的方法并环绕增强 优势: - 1. 业务类只需要关注业务逻辑本身,保证 ...
- docker与虚拟化的联系与区别
虚拟化技术是一个总称,是一系列实现虚拟技术的统称.从广义上来说,虚拟化技术包括了虚拟机技术和容器技术, 所谓虚拟化技术最大的特点就是将一个真实的机器进行虚拟地分割,然后分割出来的部分可以独立使用 ...
- springboot整合docker部署(两种构建Docker镜像方式)
项目结构 package hello; import org.springframework.boot.SpringApplication; import org.springframework.bo ...
- Redis的订阅发布
using System; using System.Collections.Generic; using System.Linq; using System.Text; using ServiceS ...