POJ1185 炮兵阵地
司令部的将军们打算在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 炮兵阵地的更多相关文章
- [poj1185]炮兵阵地_状压dp
炮兵阵地 poj-1185 题目大意:给出n列m行,在其中添加炮兵,问最多能加的炮兵数. 注释:n<=100,m<=10.然后只能在平原的地方建立炮兵. 想法:第2到状压dp,++.这题显 ...
- POJ1185炮兵阵地【动态规划】
炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 26892 Accepted: 10396 Descriptio ...
- poj1185 炮兵阵地【状压DP】
炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 32802 Accepted: 12650 Descriptio ...
- POJ1185 炮兵阵地 —— 状压DP
题目链接:http://poj.org/problem?id=1185 炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions ...
- POJ1185 炮兵阵地 和 POJ2411 Mondriaan's Dream
炮兵阵地 Language:Default 炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 34008 Accepted ...
- poj1185炮兵阵地
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> ...
- POJ1185 - 炮兵阵地(状态压缩DP)
题目大意 中文的..直接搬过来... 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平 ...
- POJ1185 炮兵阵地 状态压缩
因为不知道不同的博客怎么转,就把别人的复制过来了,这个题解写的非常好,原地址为: http://hi.baidu.com/wangxustf/item/9138f80ce2292b8903ce1bc7 ...
- poj1185炮兵阵地 正确代码及错误代码分析
Solution:状态压缩 因为设置炮兵的局限性(同行两炮兵相差要大于2),一行10个数最多有60种可能性(程序计算) 其中判断可能性的好方法是: if ((i & (i << 1 ...
随机推荐
- 解决Ehcache缓存警告问题
警告: Creating a new instance of CacheManager using the diskStorePath "D:\Apache Tomcat 6.0.18\te ...
- Delete Node in a Linked List
Write a function to delete a node (except the tail) in a singly linked list, given only access to th ...
- Linux 信号详解二(信号分类,信号处理,kill)
信号分类 信号分为可靠信号和不可靠信号 不可靠信号的缺点 ①:处理完信号,需要重新再注册信号:②信号可能丢失. Linux已经对缺点①做了优化,现在的不可靠问题主要指的是信号可能丢失 信号还可以分为实 ...
- QT 文件操作
QT提供了QFile类用于文件读写 QFile可以读写文本文件,也可以读写二进制文件 #include "widget.h" #include <QGridLayout> ...
- web学习第一章
web学习第一章 我是大概9月10日开始走上IT之路的,一开始学习了小段时间的自动化办公软件, 昨天我开始学习客户端网页编程,我了解什么是WEB,一些比较老古董的计算模式和发展历史,印象最让我深刻 ...
- U3D杂记
1,点击UI上的登录按钮,从脚本发出ioo.netmanager.SendConnet->进入CS->soketclient.sendconnet...->netmanager调用 ...
- dirtycow漏洞
dirtycow漏洞,原理还没看懂,找了几个PoC实验了一下. dirtyc0w.c我在CentOS和Kali上都失败了 pokemon.c在CentOS上成功修改了只读文件,不过修改的不是很顺利,结 ...
- ASP.NET Web API Help Pages using Swagger
Understanding the various methods of an API can be a challenge for a developer when building a consu ...
- sql基本命令
--------------------------------------------------------SQL基本命令开始----------------------------------- ...
- Java面试知识点总结
本篇文章会对面试中常遇到的Java技术点进行全面深入的总结,帮助我们在面试中更加得心应手,不参加面试的同学也能够借此机会梳理一下自己的知识体系,进行查漏补缺(阅读本文需要有一定的Java基础:若您初涉 ...