唔,想到了状压之后就不会了……实在是菜

考虑压两行,设$f_{i, j, k}$表示当前到第$i$行,上一行是$j$状态,前一行是$k$状态的最多能放的炮兵的数量。

发现第一维还可以滚掉,好像可以转移了。

但是,这样子$100 * 1024 * 1024 * 1024$时间炸了……怎么办?

考虑先不考虑题目中给出的不能放的格子的贡献,预处理出所有可行解,根据互不侵犯的套路,对于一个状态$i$,在这题中只要满足$i \& (i >> 1)$、$i \& (i >> 2)$、$i \& (i  << 1)$、$i \& (i << 2)$全部都是$0$,那么就是一个合法状态了吧。

对于一个合法状态(记编号为$i$),只要计算出有多少个$1$就相当于可以放多少个炮兵了吧,记这个数量为$num_i$。

一行最多才$10$列,一个炮兵可以打$5$格,发现预处理之后只有$60$来个有效状态了(状态数记为$tot$),$O(ntot^3)$可以承受了。

写一下转移方程:

    $f_{1, i, 0} = num_i$。

    $f_{2, i, j} = max(f_{1, j, 0} + num_i)$  $i, j$不冲突且$i$和第二行的地图不冲突。

    $f_{i, j, k} = max(f_{i - 1, k, t} + num_j)$  $j,k$ 、$k, t$、$j, t$不冲突且$j$和第$i$行的地图不冲突。

答案  $ans = max(f_{n, i, j})$。

注意第二行要分开处理。

时间复杂度$O(ntot^3)$,约为$O(n^4)$。

以后要记得复习!

Code:

#include <cstdio>
#include <cstring>
using namespace std; const int N = ; int n, m, a[N], tot = , b[N], num[N], f[N][N][N]; inline void chkMax(int &x, int y) {
if(y > x) x = y;
} inline int bitCnt(int now) {
int res = ;
for(; now > ; now >>= )
res += (now & );
return res;
} int main() {
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++) {
char str[];
scanf("%s", str + );
for(int j = ; j <= m; j++)
if(str[j] == 'H') a[i] |= ( << (j - ));
} for(int i = ; i < ( << m); i++)
if(!(i & (i << )) && !(i & (i << )) && !(i & (i >> )) && !(i & (i >> ))) {
++tot;
b[tot] = i, num[tot] = bitCnt(i);
if(!(a[] & b[tot])) f[][tot][] = num[tot];
} for(int i = ; i <= tot; i++)
for(int j = ; j <= tot; j++)
if(!(a[] & b[j]) && !(b[i] & b[j]))
chkMax(f[][j][i], f[][i][] + num[j]); for(int i = ; i <= n; i++)
for(int j = ; j <= tot; j++) {
if(a[i] & b[j]) continue;
for(int k = ; k <= tot; k++) {
if(b[j] & b[k]) continue;
for(int t = ; t <= tot; t++) {
if((b[k] & b[t]) || (b[t] & b[j])) continue;
chkMax(f[i][j][k], f[i - ][k][t] + num[j]);
}
}
} int ans = ;
for(int i = ; i <= tot; i++)
for(int j = ; j <= tot; j++)
chkMax(ans, f[n][i][j]); printf("%d\n", ans);
return ;
}

Luogu 2704 [NOI2001]炮兵阵地的更多相关文章

  1. 洛谷2704 [NOI2001]炮兵阵地

    题目戳这里 Solution 状压DP很好的入门题,用熟练位运算貌似也没那么难. 首先分析一下题目: 看见n=100,m=10,立马就想到了状压,看起来也像DP,所以我们还是采用行号为阶段的状压DP. ...

  2. luogu P2704 [NOI2001]炮兵阵地

    题目描述 司令部的将军们打算在NM的网格地图上部署他们的炮兵部队.一个NM的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P" ...

  3. 状压dp:luogu P2704 [NOI2001]炮兵阵地

    https://www.luogu.org/problemnew/show/P2704 知识点:1.滚动数组:取模实现 2.位运算优先级最低 顾是if(!(a&b))而不是if(!a& ...

  4. [洛谷P2704] [NOI2001]炮兵阵地

    洛谷题目链接:[NOI2001]炮兵阵地 题目描述 司令部的将军们打算在NM的网格地图上部署他们的炮兵部队.一个NM的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示), ...

  5. C++ 洛谷 P2704 [NOI2001]炮兵阵地

    P2704 [NOI2001]炮兵阵地 没学状压DP的看一下 此题意思很简单,如下图,就是十字架上的不能有两个点放炮兵. 在做此题前,先做一下玉米田 玉米田题解 分析: 而m即一行的个数小于等于10, ...

  6. P2704 [NOI2001]炮兵阵地 (状压DP)

    题目: P2704 [NOI2001]炮兵阵地 解析: 和互不侵犯一样 就是多了一格 用\(f[i][j][k]\)表示第i行,上一行状态为\(j\),上上行状态为\(k\)的最多的可以放的炮兵 发现 ...

  7. 洛谷P2704 [NOI2001]炮兵阵地 [状压DP]

    题目传送门 炮兵阵地 题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图 ...

  8. [Poj1185][Noi2001]炮兵阵地(状压dp)

    炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 29476   Accepted: 11411 Descriptio ...

  9. NOI2001 炮兵阵地 洛谷2704

    题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P&quo ...

随机推荐

  1. 20165222《Java程序设计》——实验二 面向对象程序设计

    20165222<Java程序设计>——实验二 面向对象程序设计 提交点一.JUnit测试用例 知识点:这里就是了解测试代码的应用,测试代码的书写为:@Test assertEquals( ...

  2. memcache使用经历

    memcache可以看成是一个大内存库,因为可以集群,所以可以看成是无限大的内存库.既然是内存库,那么我们放的就是一些map了.map里就键值对,虽然内存可以通过集群的方式无限扩展,但单个键值对的大小 ...

  3. DHCP(三)

    选择阶段:即DHCP客户端选择IP地址的阶段.如果有多台DHCP服务器向该客户端发来DHCP Offer报文,客户端只接受第一个收到的DHCP Offer报文,然后以广播方式发送DHCP Reques ...

  4. HUSTOJ 昆虫繁殖(递推)

    昆虫繁殖 时间限制: 1 Sec  内存限制: 128 MB提交: 25  解决: 16[提交][状态][讨论版][命题人:quanxing] 题目描述 科学家在热带森林中发现了一种特殊的昆虫,这种昆 ...

  5. Java-Maven-Runoob:Maven IntelliJ

    ylbtech-Java-Maven-Runoob:Maven IntelliJ 1.返回顶部 1. Maven IntelliJ IntelliJ IDEA 已经内建了对 Maven 的支持.我们在 ...

  6. 转:oracle常见重要视图-v$sql,v$sql_plan,v$sqltext,v$sqlarea,v$sql_plan_statistcs

    v$sql V$SQL中存储具体的SQL语句. 一条语句可以映射多个cursor,因为对象所指的cursor可以有不同用户(如例1).如果有多个cursor(子游标)存在,在V$SQLAREA为所有c ...

  7. python开发模块基础:异常处理&hashlib&logging&configparser

    一,异常处理 # 异常处理代码 try: f = open('file', 'w') except ValueError: print('请输入一个数字') except Exception as e ...

  8. git学习2 - 安装

    msysgit是Windows版的Git,从https://git-for-windows.github.io下载(网速慢的同学请移步国内镜像),然后按默认选项安装即可. 安装完成后,在开始菜单里找到 ...

  9. vs2017 android demo

    vs2017自安装以后就没怎么打开过,虽然12出的时候用10,15出的时候用13,17出的时候用15,但我依然坚持不用也装上再说的理念. 1.vs2017开发IOS和Android安装所必不可少的,u ...

  10. PHP操作Redis(一) PHP连接Redis,含Redis密码验证、指定某一Redis数据库

    台服务器上都快开启200个redis实例了,看着就崩溃了.这么做无非就是想让不同类型的数据属于不同的应用程序而彼此分开. 那么,redis有没有什么方法使不同的应用程序数据彼此分开同时又存储在相同的实 ...