题目描述 Description

司令部的将军们打算在N × M的网格地图上部署他们的炮兵部队。一个N × M的地图由N行M列组成,地图的每一格可能是山地(用"H"表示),也可能是平原(用"P"表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队 (山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图
上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。
现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围
内),在整个地图区域内最多能够摆放多少我军的炮兵部队。

输入描述
Input Description

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

输出描述
Output Description

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

样例输入
Sample Input

5 4
PHPP
PPHH
PPPP
PHPP
PHHP

样例输出
Sample Output

6

正解:状压DP

解题报告:

  今天考试T4。

  这是一道状压DP裸题,我一上来就看到这道题,就知道是NOI2001原题,然而我并没有想到怎么做。因为我一直很纠结这一行的决策会受上两行的影响,所以总在想着用一个什么三进制数来表示,然而总是没想通。其实并不需要三进制,就用常规的二进制思路就可以做这道题了。我用一个二进制数S,1表示放炮兵,0表示不放,显然对于每一行可以预处理一下哪些状态是可行的。位运算可以大大加速预处理速度。并且我们可以发现,一行的可行的状态数很少,而且绝对不会超过60。那么这就很好做了,我预处理出每一行的可行状态,存下来,并且算一下当前状态下的炮兵数量,每次枚举的时候我只考虑这些可行状态,就可以大大加速,避免了许多无用状态的讨论。然后,因为当前行的决策要受上两行的影响,既然要受影响,那么我不妨把状态记下来。我用f[i][S1][S2]表示第i行放状态为S1,i-1行放S2的最大值。这样的话转移也很明了了,我枚举一个i-2行的状态K1,所以f[i][S1][S2]=max(f[i-1][S2][K1]+cnt[S1],f[i][S1][S2]),也就是说我每次需要枚举三个状态。显然,第一行我们需要特殊处理,直接把第一行的所有情况算出来,为了方便处理边界,我可以给第0行增加一种状态0,这样方便转移。其余的就是一些细节了,比如果S1、S2、K1互不冲突的判断,位运算可以随便过啦。

 //It is made by jump~
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long LL;
const int inf = (<<);
const int MAXN = ;
const int MAXM = ;
int n,m,ans,end;
int a[MAXN][];
char ch[];
int f[MAXN][][];//f[i][S1][S2]表示第i行放状态为S1,i-1行放S2的最大值
int dix[MAXN];
int mp[MAXN][],cnt[MAXN][],num[MAXN];//每一行可行状态最多60种 inline int getint()
{
int w=,q=; char c=getchar();
while((c<'' || c>'') && c!='-') c=getchar(); if(c=='-') q=,c=getchar();
while (c>='' && c<='') w=w*+c-'', c=getchar(); return q ? -w : w;
} inline int get_cnt(int s){ int total=; while(s) total+=s&,s>>=; return total; } inline void work(){
n=getint(); m=getint();
for(int i=;i<=n;i++) {
scanf("%s",ch);
for(int j=;j<m;j++) {
if(ch[j]=='P') a[i][j+]=;
else a[i][j+]=;
dix[i]|=a[i][j+]*(<<j);
}
}
end=(<<m)-;
for(int i=;i<=n;i++) {
for(int s=;s<=end;s++) {
if(( s&(s<<) )!=) continue; if(( s&(s<<) )!=) continue;
if((dix[i]&s)!=s) continue;
num[i]++; mp[i][num[i]]=s; cnt[i][num[i]]=get_cnt(s);
}
}
num[]++; for(int i=;i<=n;i++) for(int j=;j<=num[];j++) f[][j][]=cnt[][j];
int now,k1,k2;
for(int i=;i<=n;i++) {
for(int j=;j<=num[i-];j++) {
k1=mp[i-][j];
for(int k=;k<=num[i-];k++) {
k2=mp[i-][k]; if(f[i-][j][k]==) continue;
for(int l=;l<=num[i];l++) {
now=mp[i][l]; if((now&k1)!=) continue; if((now&k2)!=) continue;
f[i][l][j]=max(f[i][l][j],f[i-][j][k]+cnt[i][l]);
}
}
}
}
for(int i=;i<=num[n];i++) for(int j=;j<=num[n-];j++) ans=max(ans,f[n][i][j]);
printf("%d",ans);
} int main()
{
work();
return ;
}

POJ1185 炮兵阵地的更多相关文章

  1. [poj1185]炮兵阵地_状压dp

    炮兵阵地 poj-1185 题目大意:给出n列m行,在其中添加炮兵,问最多能加的炮兵数. 注释:n<=100,m<=10.然后只能在平原的地方建立炮兵. 想法:第2到状压dp,++.这题显 ...

  2. POJ1185炮兵阵地【动态规划】

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

  3. poj1185 炮兵阵地【状压DP】

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

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

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

  5. POJ1185 炮兵阵地 和 POJ2411 Mondriaan's Dream

    炮兵阵地 Language:Default 炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 34008 Accepted ...

  6. poj1185炮兵阵地

    #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> ...

  7. POJ1185 - 炮兵阵地(状态压缩DP)

    题目大意 中文的..直接搬过来... 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平 ...

  8. POJ1185 炮兵阵地 状态压缩

    因为不知道不同的博客怎么转,就把别人的复制过来了,这个题解写的非常好,原地址为: http://hi.baidu.com/wangxustf/item/9138f80ce2292b8903ce1bc7 ...

  9. poj1185炮兵阵地 正确代码及错误代码分析

    Solution:状态压缩 因为设置炮兵的局限性(同行两炮兵相差要大于2),一行10个数最多有60种可能性(程序计算) 其中判断可能性的好方法是: if ((i & (i << 1 ...

随机推荐

  1. Javascript中document.execCommand()的用法

    document.execCommand()方法处理Html数据时常用语法格式如下:document.execCommand(sCommand[,交互方式, 动态参数]) 其中:sCommand为指令 ...

  2. 兼容利器之X-UA-Compatible

    文档兼容模式 不同浏览器之间经常产生各种奇异的现象,为了解决这些问题,使用以下方法,发现很多问题自动消失不见了 <meta http-equiv="X-UA-Compatible&qu ...

  3. 重构Web Api程序(Api Controller和Entity)续篇

    昨天有写总结<重构Web Api程序(Api Controller和Entity)>http://www.cnblogs.com/insus/p/4350111.html,把一些数据交换的 ...

  4. [py]shell着色

    print "\033[32;1myou are 30 older and little than 40\033[0m"

  5. HTML5 postMessage 跨域交换数据

    前言 之前简单讲解了利用script标签(jsonp)以及iframe标签(window.name.location.hash)来跨域交换数据,今天我们来学习一下HTML5的api,利用postMes ...

  6. JavaScript 总结几个提高性能知识点

    前段时间花时间看了大半的<High Performance JavaScript>这本书啊,然后就开始忙项目了,庆幸最忙的一周已经熬过去了.由于空不出时间,这个月写的学习笔记也不多,忙完最 ...

  7. php缓存技术(减少数据库服务器压力)

    静态缓存(保存在磁盘上的静态文件,用PHP生成数据放入静态文件中) a)  php操作缓存 i.  生成缓存 ii.  获取缓存 iii. 删除缓存 判断目录是否存在:is_dir() dirname ...

  8. unittest使用过程中sys.exit(not self.result.wasSuccessful())

    起因: 在运行下面的unittest过程中出现了个Traceback: 被测试脚本: # splitter.py def split(line, types=None, delimiter=None) ...

  9. js的数组

    转载:http://blog.163.com/sammer_rui/blog/static/846200442010717900634/ https://developer.mozilla.org/z ...

  10. mac搭建mamp环境

    1 先安装homebrew; 执行:cd /usr/local; 非root用户执行: ruby -e "$(curl -fsSL https://raw.githubusercontent ...