【传送门】

【题目大意】

司令部的将军们打算在 \(N\times M\) 的网格地图上部署他们的炮兵部队。一个 \(N\times M\) 的地图由 \(N\) 行 \(M\) 列组成,地图的每一格可能是山地(用 H 表示),也可能是平原(用 P 表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:

求最多能摆放的炮兵部队的数量。

【关键词】

  • 状压DP
  • 预处理
  • 进制运算

【分析】

可以说这道题是状压\(DP\)的经典例题了,我们思考,每一行的状态只会被当前这一行的地形和前两行的状态束缚,所以我们可以预处理第一行与第二行,然后枚举每一行的状态进行\(DP\)转移。

细节方面就看代码吧。

【Code】

//#include<bits/stdc++.h>
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define debug() puts("FBI WARNING!")
#define ll long long using namespace std;
inline int read(){
int f = 1, x = 0;char ch;
do { ch = getchar(); if (ch == '-') f = -1; } while (ch < '0'||ch>'9');
do {x = x*10+ch-'0'; ch = getchar(); } while (ch >= '0' && ch <= '9');
return f*x;
}
int n, m, M;
int maps[105], num[(1<<11)], c[80], len;
char tmp[15];
int dp[105][80][80], ans; inline bool judge(int a, int b) {
if ((a & b) == 0) return 1;
else return 0;
} inline bool can(int x) {
if (((x << 1) & x) || (x << 2) & x || (x >> 1) & x || (x >> 2) & x) return 0;
else return 1;
} inline void init() {
/*
预处理num[]
*/
for (int i = 1;i < M; ++i) {
int x = i;
while (x) {
num[i]+=x%2;
x >>= 1;
}
}
/*
预处理c[]
*/
for (int i = 0;i < M; ++i) {
if (can(i)) {
c[++len] = i;
}
}
} int main(){
n = read(); m = read();
M = (1 << m);
init();
for (int i = 1;i <= n; ++i) {
scanf("%s", tmp);
for (int j = 0;j < m; ++j)
if (tmp[j] == 'H')
maps[i] += (1 << j);
}
/*for (int i = 0;i < n; ++i) {
printf("%d\n", maps[i]);
}*/
for (int i = 1;i <= len; ++i) { // 第一行处理
if (judge(c[i], maps[1]))
dp[1][i][1] = num[c[i]];
}
/*for (int i = 0;i < M; ++i) {
printf("dp[0][%d][0] = %d can:%d, judge:%d\n", i, dp[0][i][0], can(i), judge(i, maps[0]));
}*/
for (int i = 1;i <= len; ++i) { // 第二行处理
if (judge(c[i], maps[2]))
for (int j = 1;j <= len; ++j) {
if (judge(c[j], maps[1]) && judge(c[i], c[j]))
dp[2][i][j] = max(dp[2][i][j], dp[1][j][1]+num[c[i]]);
}
}
for (int i = 3;i <= n; ++i) { // DP
for (int j = 1;j <= len; ++j) {
if (judge(c[j], maps[i]))
for (int k = 1;k <= len; ++k) {
if (judge(c[j], c[k]) && judge(c[k], maps[i-1])) {
for (int s = 1;s <= len; ++s) {
if (judge(c[s], c[j]) && judge(c[s], c[k]) && judge(c[s], maps[i-2])) {
dp[i][j][k] = max(dp[i][j][k], dp[i-1][k][s]+num[c[j]]);
}
}
}
}
}
}
for (int i = 1;i <= len; ++i) { //求解答案
for (int j = 1;j <= len; ++j) {
ans = max(ans, dp[n][i][j]);
}
}
printf("%d", ans);
return 0;
}

【简●解】POJ 1185,LG P2704【炮兵阵地】的更多相关文章

  1. P2704 炮兵阵地

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

  2. [LUOGU] P2704 炮兵阵地

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

  3. luogu P2704 炮兵阵地(经典状态压缩DP)

    方格有m*n个格子,一共有2^(m+n)种排列,很显然不能使用暴力法,因而选用动态规划求解. 求解DP问题一般有3步,即定义出一个状态 求出状态转移方程 再用算法实现.多数DP题难youguan点在于 ...

  4. 洛谷P2704 炮兵阵地

    本题过于经典...... 对于这种网格状压DP,套路一波刷表法DFS转移就没了. 三进制状压,0表示当前,上一个都没有.1表示当前无,上一个有.2表示当前有. 转移的条件就是上一行为0,当前不是山地, ...

  5. 【Luogu】P2704炮兵阵地(状压DP)

    题目链接 话说还真没见过能影响两行的状压.想了半天想出来f数组再多一维就能表示,但是没想到怎么才能不爆空间…… 也是从这道题里学到的一个妙招. 可以把合法状态存到一个数组里,然后用数组下标来映射状态. ...

  6. POJ 1185 炮兵阵地 状压dp

    题目链接: http://poj.org/problem?id=1185 炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K 问题描述 司令部的将军们打算在N*M ...

  7. POJ 1185 炮兵阵地(状压DP)

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

  8. POJ 1185 状态压缩DP 炮兵阵地

    题目直达车:   POJ 1185 炮兵阵地 分析: 列( <=10 )的数据比较小, 一般会想到状压DP. Ⅰ.如果一行10全个‘P’,满足题意的状态不超过60种(可手动枚举). Ⅱ.用DFS ...

  9. POJ 1185 炮兵阵地(动态规划+状态压缩)

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

随机推荐

  1. ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(七) 学生信息增删

    前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/asp ...

  2. 51nod 1051 最大子矩阵和(DP)

    题意 略 分析 一道经典的DP题,但是我弱到差点做不出来,真的垃圾 设置\(sum(i,j)代表1-i行第j列的前缀和\),然后枚举行i和行j,再枚举列k,做一遍类似一维的最大子段和即可 #inclu ...

  3. U3D 的一些基础优化

    1.在使用数组或ArrayList对象时应当注意 [csharp] view plaincopy length=myArray.Length; for(int i=0;i<length;i++) ...

  4. python __builtins__ range类 (56)

    56.'range',  创建一个整数列表 class range(object) | range(stop) -> range object | range(start, stop[, ste ...

  5. Java面试必刷常见真题200+ ,让你“过五关,斩六将”,轻松入大厂

    这份面试清单是我从 2015 年做 TeamLeader 之后开始收集的,一方面是给公司招聘用,另一方面是想用它来挖掘我在 Java 技术栈中的技术盲点,然后修复和完善它,以此来提高自己的技术水平.虽 ...

  6. The local variable fruit may not have been initialized 错误

    eclipse错误提示如图: 错误代码如图: 首先这错误的翻译是:局部变量"水果"尚未初始化,所以对象该如何初始化呢,我百度之后找到了答案,修改过后如下图所示. 这个错误的问题所在 ...

  7. Luogu P1429 平面最近点对 【分治】By cellur925

    题目传送门 题目大意:给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的.$n$<=100000. $Algorithm$ 最朴素的$n^2$枚举肯定 ...

  8. (二)SpringBoot整合常用框架Druid连接池

    一,在Pom.xml文件加入依赖 找到<dependencies></dependencies>标签,在标签中添加Druid依赖 <dependency> < ...

  9. SpringBoot的配置文件加载顺序以及如何获取jar包里的资源路径

    一.读取配置文件的四种方式 这四种配置文件放置方式的读取优先级依次递减,具体可以查看官方文档. 1.1jar包同级目录下的config文件夹里的配置文件 其实我以前就见过这种方式了,只是不知道怎么做的 ...

  10. AtCoder Grand Contest 016 F - Games on DAG

    题目传送门:https://agc016.contest.atcoder.jp/tasks/agc016_f 题目大意: 给定一个\(N\)点\(M\)边的DAG,\(x_i\)有边连向\(y_i\) ...