洛谷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$状态的最多能放的炮兵的数量. 发现第一维还可以滚掉,好像可以转移 ...
随机推荐
- Android Gradle基础实践
1,gradle是全新的一种IDE编程环境,Android Studio集成了Gradle IDE 2,要下载gradle(比方gradle-2.10)解压.配置环境变量.比方G:\Program ...
- 关于ng-router嵌套使用和总结
那是某个下午的review代码的过程.js中有一段html,像是这样. var html = '<div>...此处还有很多html代码....</div>' 我的同事想我提出 ...
- JAVA Eclipse如何修改Android程序名称
Values中修改strings.xml中的app_name即可 注意他是连接到AndroidManifest.xml文件的
- JDBC性能优化方案
最近用到了利用JDBC查询Oracle数据库.可是查询效率不尽人意.研究了一下JDBC方面能够优化的地方,在这里跟大家分享一下. 1.设置最优的预取值 defaultRowP ...
- css 中 important 的用法
css 中 important 的如何使用? important对 一个良好(或者是标准)的浏览器来说,不仅仅是从顺序上提升代码的优先级,还可以用来提升class的优先级(比如firefox), ...
- TCP/IP详解 卷一(第十七章 TCP:传输控制协议)
与UDP协议相比,TCP提供一种面向连接的.可靠的字节流服务. TCP首部 跟UDP一样,TCP数据被封装在一个IP数据报中,下面显示TCP的首部数据格式 每个TCP段都包含源端和目的端的端口号,用于 ...
- 不得不看的Java代码性能优化总结
原文:https://blog.csdn.net/mr_smile2014/article/details/50112723 前言 代码优化,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么 ...
- web-小知识点(随记)
1.position:fixed:窗口定位的时候(在刷新页面时若未出现.得稍等一会的话,就直接把需要定位的内容写在<html>标签的首部.这样页面加载html的时候首先加载fixed定位的 ...
- String、StringBuffer、StringBuilder区别并验证
© 版权声明:本文为博主原创文章,转载请注明出处 String.StringBuffer.StringBuilder的区别 1.String是一个常量,其对象一旦创建完毕就无法改变,当使用“+”拼接字 ...
- oracle中的minus数据比对
1.要有唯一索引或者主键作为前提,减少数据冲突的数量,如示例标红的地方: 2.当有in查询的时候,尽量用exists,这样能提高查询效率: create table TF_F_USER_DIFF1 ...