洛谷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$状态的最多能放的炮兵的数量. 发现第一维还可以滚掉,好像可以转移 ...
随机推荐
- ubuntu 备份清理tomcat日志,并且删除七天之前的日志
创建文件clear_tomcat_log.sh #!/bin/bash logs_paths[0]="app_tomcat7_8080"; logs_paths[1]=" ...
- RAP + MOCK
前后端分离式开发的思考 目前大部分公司都实行了前后端分离开发.然而在项目开发过程当中,经常会遇到以下几个尴尬的场景: 1.前端开发依赖于后端接口数据,需要与后端接口联调才能获得数据展示,从而拖慢了开发 ...
- <context:annotation-config/>、<context:component-scan/>
在基于主机方式配置Spring的配置文件中,你可能会见到<context:annotation-config/>这样一条配置,他的作用是式地向 Spring 容器注册 AutowiredA ...
- Ctrl/Alt 快捷键
Ctrl+S 保存 Ctrl+W 关闭程序 Ctrl+N 新建文档 Ctrl+O 打开(选择打开其他文档) Ctrl+Z 撤销 Ctrl+F 查找 Ctrl+X 剪切 Ct ...
- angular中通过CSS使下拉列表默认值变灰
angular版本:angular5 先看效果图: drop down的样式是我用CSS样式控制的,没有用插件.想要改变Drop Down List里的默认值的颜色,我的思路是这样的. 在<se ...
- .net core 2.0小白笔记(一):开发运行环境搭建
小白一枚,有任何不妥之处敬请指教 这里不讨论什么设计模式,什么架构,什么什么,就是入门,简单的入门,虽然能跨平台,但是这里还是在win的环境下进行,不扯的那么远 其实官网文档写的挺不错的了,就是偶尔有 ...
- Dictionary及KeyValuePair使用
/// <summary> /// 除去数组中的空值和签名参数并以字母a到z的顺序排序 /// </summary> /// <param name="dicA ...
- SVN 钩子操作-同步更新web目录
一个简单的钩子演示:也可以网上搜索其他高级的 本次想要达到的功能是:每次用户commit 到仓库后,仓库的钩子会自动把程序又更新的www/的web发布目录 1.现在web目录下创建一个test.com ...
- android开发系列之aidl
aidl在android开发中的主要作用就是跨进程通讯来着,说到进程相比很多人都是非常熟悉了,但是为什么会有跨进程通讯这个概念呢?原来在android系统中,有这么一套安全机制,为了各个Apk数据的独 ...
- [译]GLUT教程 - 整合代码7
Lighthouse3d.com >> GLUT Tutorial >> Extras >> The Code So Far VII 以下是子窗体的最终版本代码. ...