http://poj.org/problem?id=1185

炮兵阵地
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 29176   Accepted: 11303

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

   很有趣的题目,由于炮兵攻击范围达到了两行所以我们枚举当前行状态时肯定需要前两行的状态,有一个显然的方程为 f[i][j][k]=MAX{  f[i-1][v][j] | if(i,j,k对应的三行的状态可以共存 }
每行状态最多210,这样算的话肯定会T,但是仔细想想会发现合法的状态最多只有60多个,因为只要存在相邻的1就不合法,所以可以筛去很多的状态,将这些状态离散化,a[i]为第i个合法状态,t[i]为第i个状态中‘1’的个数。接着我们就能用f[i][j][k]表示第i行为第k个合法状态,第i-1行为第j个合法状态时最大炮兵个数,复杂度大大降低。注意每次都要判断三个状态能否放在对应的三行上以及是否可以共存,这些关系的判断使用打表法存下,因为要进行多次判断,第一次直接计算结果T了,打表之后250ms A了,虽然不是很快- -

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
int e[][];
int f[][][];
int N,M,tot,all;
int a[],t[];
int g[][];
int _g[][];
int sol(int x)
{
int r=;
for(int j=;j<M;++j)
{
if(x&(<<j)) {
r++;
for(int i=-;i<=;++i)
{
if(i==||j+i<||j+i>=M) continue;
if(x&(<<(j+i))) return -;
}
}
}
return r;
}
void init()
{
for(int i=;i<all;++i)
{
int x=sol(i);
if(x!=-){
a[tot]=i;
t[tot++]=x;
}
}
}
bool ok(int _a,int x)
{
int A=a[_a];
for(int i=;i<M;++i)
if((A&(<<i))&&e[x][M-i]) return ;
return ;
}
bool match(int _a,int _b)
{
int A=a[_a],B=a[_b];
for(int i=;i<M;++i)
if((A&(<<i))&&(B&(<<i))) return ;
return ;
}
int main()
{
int i,j,k=;
while(scanf("%d%d",&N,&M)==){tot=;
all=(<<M);memset(e,,sizeof(e));
memset(f,,sizeof(f));
memset(g,-,sizeof(g));
memset(_g,-,sizeof(_g));
for(i=;i<=N+;++i)
for(j=;j<=M;++j){
char c;
scanf(" %c",&c);
e[i][j]=c=='P'?:;
}
init();
for(i=;i<tot;++i)
for(j=;j<=N+;++j)
_g[i][j]=ok(i,j);
for(i=;i<tot;++i)
for(j=;j<tot;j++)
g[i][j]=match(i,j);
for(i=;i<=N+;++i)
{
for(int t1=;t1<tot;++t1)
{
if(!_g[t1][i-]) continue;
for(int t2=;t2<tot;++t2)
{
if(!_g[t2][i-]||!g[t1][t2]) continue;
for(int t3=;t3<tot;++t3)
{
if(!_g[t3][i]||!g[t2][t3]||!g[t1][t3]) continue;
if(f[i][t2][t3]<f[i-][t1][t2]+t[t3])f[i][t2][t3]=f[i-][t1][t2]+t[t3];
}
}
}
}
int ans=;
for(int t1=;t1<tot;++t1)
for(int t2=;t2<tot;++t2)
if(ans<f[N+][t1][t2])ans=f[N+][t1][t2];
printf("%d\n",ans);
}
return ;
}

poj 1185 状压dp+优化的更多相关文章

  1. poj 1185(状压dp)

    题目链接:http://poj.org/problem?id=1185 思路:状态压缩经典题目,dp[i][j][k]表示第i行状态为j,(i-1)行状态为k时最多可以放置的士兵个数,于是我们可以得到 ...

  2. 炮兵阵地(POJ 1185状压dp)

    题意:n*m地图'H'能放'p'不能放,布兵的方格上下左右不能布兵,给你地图求最大布兵数 分析:关系到前两行,所以dp[i][j][k]第i行状态为j,i-1行状态为k时的最大布兵数, 先求出所有可行 ...

  3. POJ1038 Bugs Integrated, Inc 状压DP+优化

    (1) 最简单的4^10*N的枚举(理论上20%) (2) 优化优化200^3*N的枚举(理论上至少50%) (3) Dfs优化状压dp O(我不知道,反正过不了,需要再优化)(理论上80%) (4) ...

  4. POJ 3254 (状压DP) Corn Fields

    基础的状压DP,因为是将状态压缩到一个整数中,所以会涉及到很多比较巧妙的位运算. 我们可以先把输入中每行的01压缩成一个整数. 判断一个状态是否有相邻1: 如果 x & (x << ...

  5. poj 1170状压dp

    题目链接:https://vjudge.net/problem/POJ-1170 题意:输入n,表示有那种物品,接下来n行,每行a,b,c三个变量,a表示物品种类,b是物品数量,c代表物品的单价.接下 ...

  6. hdu 1185 状压dp 好题 (当前状态与上两行有关系)

    /* 状压dp 刚开始&写成&&看了好长时间T0T. 状态转移方程 dp[i][k][j]=Max(dp[i][k][j],dp[i-1][l][k]+num[i][j]);( ...

  7. POJ 2411 状压DP经典

    Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 16771   Accepted: 968 ...

  8. POJ 3254 状压DP

    题目大意: 一个农民有一片n行m列 的农场   n和m 范围[1,12]  对于每一块土地 ,1代表可以种地,0代表不能种. 因为农夫要种草喂牛,牛吃草不能挨着,所以农夫种菜的每一块都不能有公共边. ...

  9. poj 3254 状压dp入门题

    1.poj 3254  Corn Fields    状态压缩dp入门题 2.总结:二进制实在巧妙,以前从来没想过可以这样用. 题意:n行m列,1表示肥沃,0表示贫瘠,把牛放在肥沃处,要求所有牛不能相 ...

随机推荐

  1. 安装VS2013 2015 需要IE10浏览器 跳过的方法

    安装VS2013 如果浏览器版本较旧的话会提示要求你更新到IE10版本,很麻烦,那么我们如何跳过呢? 复制下面代码粘贴到文本文档里,修改文本txt后缀为bat,右键管理员运行. @ECHO OFF   ...

  2. Django 之 URL(路由)分发机制

    本质 (1):它的本质是 URL 模式以及要为该 URL 模式调用的视图函数之间的映射表. django-admin.py startproject 运行时,该脚本会自动为你建了一份 URLconf( ...

  3. python并发编程&多线程(二)

    前导理论知识见:python并发编程&多线程(一) 一 threading模块介绍 multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性 官网链 ...

  4. ThreadPoolExecutor 线程池任务队列分析 与 利特尔法则(Little's law)

    一. 演示 public class ThreadPoolTest { static class MyThread implements Runnable { private String name; ...

  5. time 和 datetime 模块

    在Python中,通常有这几种方式来表示时间: 时间戳(timestamp):通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量.我们运行“type(time.time( ...

  6. Python 学习之旅

    流程图 第一章  Python简介 第二章  Python基础 第三章  流程控制 第四章  字符编码 第五章  文件处理 第六章  函数 第七章 模块与包 第八章 面向对象 第九章 异常处理 第十章 ...

  7. 转:使用awk命令获取文本的某一行,某一列

    1.打印文件的第一列(域)                 : awk '{print $1}' filename2.打印文件的前两列(域)                 : awk '{print ...

  8. 江卓尔与比特币增发,谣言or先知-千氪

    最近,很多圈内人都在讨论比特币是否应该增发,但等等,比特币真的会增发吗?到底是真有增发计划还是某些人别有用心地在散布谣言? 那么消息是从哪里出来的?北京时间 2 月 10 日晚,莱比特矿池创始人江卓尔 ...

  9. Eclipse 变量高亮显示设置

    A:Window-> preferences->java->Editor->Mark Occurences Local variables就是变量的高亮显示

  10. 源码编译搭建LAMP

    环境版本信息: RHEL 5.3 Apache / 2.4.16 PHP / 5.4.45 mysql-5.5.45 源代码编译 安装方式 1: configure 配置 以及定制我们的软件包 2: ...