炮兵阵地
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 32802   Accepted: 12650

Description

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

如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。 
现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。 

Input

第一行包含两个由空格分割开的正整数,分别表示N和M; 
接下来的N行,每一行含有连续的M个字符('P'或者'H'),中间没有空格。按顺序表示地图中每一行的数据。N <= 100;M <= 10。

Output

仅一行,包含一个整数K,表示最多能摆放的炮兵部队的数量。

Sample Input

5 4
PHPP
PPHH
PPPP
PHPP
PHHP

Sample Output

6

Source

 
题意:
有一个n*m的格子有的格子是山,有的格子是平原。只有平原可以放一个炮兵。炮兵的攻击范围是两格,也就是说如果一个格子放了炮兵,他上下左右两格里不能再放炮兵。问这样n*m的地图中,可以最多放多少炮兵。
 
思路:
因为m是小于10的,每个格子又只有放或者不放的状态。所以我们可以考虑状压。用一个十进制数来表示某一行的放炮兵状态。第j位是1表示第j列的格子放了炮兵,0表示没有放。同理,地图上一行的山或是平原的状态也可以用十进制数来表示。
以行数i作为状态转移的阶段,转移的时候需要看的是前面两行的状态。用dp[i][j][k]表示第i行的状态时j,第i-1行的状态是k时,前i行最多的炮兵数。
显然dp[i][j][k] = max(dp[i -1][k][l]) + j的二进制表示中1的个数
并且并不是所有0~2^m-1的数都是可行的,必须要是二进制中1之间的间隔大于等于2的数才可以。
那么我们就可以首先预处理出所有可行的数,每次遍历这些数就可以了。对于每一行还需要去判断一下是否满足当前的地图状态。
刚开始用把平原当1,山当0,这样判断的时候位运算会有点麻烦。所以后面改成了用山当1,这样只需要用& == 0就可以了。
debug了超级久,今天终于找到bug了,太菜了。码力堪忧......
 #include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <cstring> using namespace std;
typedef long long LL;
#define inf 0x3f3f3f3f const int maxn = ;
int n, m, mostm;
int dp[maxn][][], dixing[maxn];
int cntone[], S[], cnt; bool valid(int i, int x)
{
if (dixing[i] & x)return false;
else return true;
} int get_one(int x)
{
int res = ;
while (x) {
res += (x & );
x >>= ;
}
return res;
} bool ok(int x)
{
if (x & (x << ))return false;
if (x & (x << )) return false;
return true;
} void getS()
{
cnt = ;
mostm = << m;
for (int i = ; i < mostm; i++) {
if (ok(i)) {
S[cnt] = i;
cntone[cnt] = get_one(i);
cnt++;
}
}
} int main()
{
while (scanf("%d%d", &n, &m) != EOF) {
getS();
memset(dixing, , sizeof(dixing));
for (int i = ; i <= n; i++) {
char tmp[];
scanf("%s", tmp);
//printf("%s", tmp + 1);
for (int j = ; j < m; j++) {
//cout<<tmp[j]<<endl;
if (tmp[j] == 'H') {
dixing[i] |= ( << (m - - j));
}
}
} memset(dp, -, sizeof(dp));
dp[][][] = ;
int ans = ;
for (int j = ; j < cnt; j++) {
if (valid(, S[j])) {
dp[][j][] = cntone[j];
ans = max(ans, dp[][j][]);
}
}
//cout<<1<<" "<<ans<<endl; for (int i = ; i <= n; i++) {
int tiaoshi = -;
for (int j = ; j < cnt; j++) {
if (valid(i, S[j])) {
for (int k = ; k < cnt; k++) {
if (valid(i - , S[k]) && (S[j] & S[k]) == ) {
int mmm = -;
for (int l = ; l < cnt; l++) {
if (valid(i - , S[l]) && dp[i - ][k][l] != - && (S[j] & S[l]) == ) {
mmm = max(mmm, dp[i - ][k][l]);
}
}
//cout<<i - 1<<" "<<mmm<<endl;
dp[i][j][k] = max(dp[i][j][k], mmm + cntone[j]);
tiaoshi = max(tiaoshi, dp[i][j][k]);
if (i == n)ans = max(ans, dp[i][j][k]);
}
}
}
}
//cout<<i<<" "<<tiaoshi<<endl;
}
printf("%d\n", ans);
} //return 0;
}

poj1185 炮兵阵地【状压DP】的更多相关文章

  1. POJ1185 炮兵阵地 —— 状压DP

    题目链接:http://poj.org/problem?id=1185 炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions ...

  2. poj1185 炮兵阵地 状压dp

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

  3. TZOJ 4912 炮兵阵地(状压dp)

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

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

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

  5. [POJ1185][NOI2001]炮兵阵地 状压DP

    题目链接:http://poj.org/problem?id=1185 很裸的状压,考虑对于一行用二进制储存每一种的状态,但是状态太多了做不了. 观察到有很多状态都是不合法的,于是我们预处理出合法的状 ...

  6. poj - 1185 炮兵阵地 状压DP 解题报告

    炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 21553   Accepted: 8363 Description ...

  7. luogu 2704 炮兵阵地 状压dp

    状压的基础题吧 第一次看感觉难上天,后来嘛就.. 套路:先根据自身状态筛出可行状态,再根据地图等其他限制条件筛选适合的状态加入答案 f i,j,k 分别代表 行数,本行状态,上行状态,再累加答案即可 ...

  8. POJ 1185 炮兵阵地 状压dp

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

  9. [NOI2001]炮兵阵地 状压DP

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

  10. 炮兵阵地 /// 状压DP oj26314

    题目大意: 炮兵阵地 设置炮兵的位置 其上两位 下两位 左两位 右两位 不能同时设置炮兵 这题是 corn fields玉米地 的升级版 可以先看下这题的注释 更详细些 第一种方法是网上大多数题解的解 ...

随机推荐

  1. e1084. 捕获错误和异常

    All errors and exceptions extend from Throwable. By catching Throwable, it is possible to handle all ...

  2. const 与#define 的比较

    const 与#define 的比较 C++ 语言可以用 const 来定义常量,也可以用 #define 来定义常量.但是前者比后 者有更多的优点: (1) const 常量有数据类型,而宏常量没有 ...

  3. VS2010 快捷键设置,快速编码1

    全屏:Shift+Alt+Enter注释选定内容:Ctrl+E+C/Crtr+E+U代码格式化:ctrl+E+F VS2008 使用小技巧——快捷键1. 怎样调整代码排版的格式?选择:编辑—>高 ...

  4. linux -- ubuntu 脚本开机自启动

    有一个脚本想在ubuntu 虚拟机开机时,自动运行. 创建脚本文件 在“/opt/lampp/”下新建一个脚本文件:lampp_start.sh #!/bin/bash /opt/lampp/lamp ...

  5. 基于Poco的UTF8、UTF16、GBK、Hex之间的转换

    /******Encoding.h*******/ #include "Poco/UnicodeConverter.h" #include "Poco/Exception ...

  6. 【Java面试题】35 List, Set, Map是否继承自Collection接口?

    Collection是最基本的集合接口,声明了适用于JAVA集合(只包括Set和List)的通用方法. Set 和List 都继承了Conllection:Set具有与Collection完全一样的接 ...

  7. java与c#的语法对比

    1,命名空间与包 C#为了把实现相似功能的类组织在一起,引入了命名空间的概念(namespace) Java中与此对应的东西叫做包(package) 2,类的访问控制方面的不同 C#只有两种:publ ...

  8. Eclipse的调试功能的10个小窍门

    你可能已经看过一些类似“关于调试的N件事”的文章了.但我想我每天大概在调试上会花掉1个小时,这是非常多的时间了.所以非常值得我们来了解一些用得到的功能,可以帮我们节约很多时间.所以在这个主题上值得我再 ...

  9. 安装并配置ROS环境1

    ros学习之路(原创博文,转载请标明出处-周学伟http://www.cnblogs.com/zxouxuewei/) 一.ros核心教程    1.安装并配置ROS环境: 注意: 学习这节课之前请按 ...

  10. ASP代码审计学习笔记 -2.XSS跨站脚本

    XSS漏洞: 漏洞代码: <% xss=request("xss") response.write(xss) %> 漏洞利用: 漏洞修复: Server.HTMLEnc ...