题面:

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

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

n <= 100,m <= 10;

题解:

观察到如此小的m,我们首先就要考虑状压,

但是每一行将会受到2行的影响,因此我们考虑压两行,

f[i][j][k]表示第i行状态为j,第i-1行状态为k的最优解,

因此我们有转移方程:

f[i][j][k]=max(f[i][j][k],f[i-1][k][l] + num[j].one);

num[j].one 表示状态j下有几个炮兵,

合法条件如下:

if(s[i] & num[j].date) continue;

if(s[i-1] & num[k].date) continue;

if(num[j].date & num[k].date) continue;

if(s[i-2] & num[l].date) continue;

if((num[j].date & num[l].date) | (num[k].date & num[l].date)) continue;

其中s[i]表示i行的限制条件,如果第t位不能放炮兵,那么这位就是1,

j , j ,l 分别为i,i-1,i-2所枚举的状态,

num[i].date表示当前状态,

因为要满足不能放炮兵的地方不放炮兵,所以s[i] & num[j].date必须为0,其他行同理,

这时你肯定注意到了,,,这是个4层循环啊!那复杂度岂不是100 * 1024 *1024 *1024?

这样的复杂度当然是不行的,观察到每个炮兵的管辖区域相对于仅仅只有10的m来说,其实是非常广的,不管怎么放,最多也就放4个炮兵而已,

因此我们可以实现找出所有初步合法状态(即满足同一行中炮兵不互相贡献的状态),一共只有59个,,,,

因此这时的复杂度就可以承受了,

而且找合法状态的时候还可以顺便就预处理出对应的炮兵个数,是不是非常方便啊~~~~~~~

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 110
int n,m,tot,ans;
int f[AC][][];
int s[AC];
char ss[AC];
struct node{
int date,one;
}num[AC];
/*观察到因为m只有10,而一个炮兵的控制区域就有5了,所以一行最多放两个
可行状态很少,m=10都只有59个,所以完全可以打表放进来啊!
f[i][j][k]表示i行状态j,上一行为k*/
inline bool cmp(node a,node b)
{
return a.date < b.date;
} void pre()
{
scanf("%d%d",&n,&m);
for(R i=;i<=n;i++)
{
scanf("%s",ss+);
for(R j=;j<=m;j++)
if(ss[j] == 'H') s[i] |= ( << (m - j));//获取这个的状态,1表示不合法
}
} void work1()
{
++tot;
for(R i=;i<=m;i++)
{
num[++tot].date=( << (i - ));
num[tot].one=;
}
for(R i=;i<=m;i++)
for(R j=i+;j<=m;j++)
{
num[++tot].date=( << (i - )) + ( << (j - ));
num[tot].one=;
}
for(R i=;i<=m;i++)
for(R j=i+;j<=m;j++)
for(R k=j+;k<=m;k++)
{
num[++tot].date=( << (i - )) + ( << (j - )) + ( << (k - ));
num[tot].one=;
}
for(R i=;i<=m;i++)
for(R j=i+;j<=m;j++)
for(R k=j+;k<=m;k++)
for(R l=k+;l<=m;l++)
{
num[++tot].date=( << (i - )) + ( << (j - )) + ( << (k - )) + ( << (l - ));
num[tot].one=;
}
// for(R i=1;i<=tot;i++)
// printf("%d have %d\n",num[i].date,num[i].one);
} void work()
{
memset(f,,sizeof(f));
for(R i=;i<=tot;i++)
{
if(s[] & num[i].date) continue;
f[][i][]=num[i].one;//获取第一行
}
for(R i=;i<=tot;i++) //枚举第二行的状态
{
if(s[] & num[i].date) continue;
for(R j=;j<=tot;j++)
{
if(s[] & num[j].date) continue;
if(num[i].date & num[j].date) continue;
f[][i][j]=f[][j][] + num[i].one;
}
}
for(R i=;i<=n;i++)//枚举到了哪一行
{
for(R j=;j<=tot;j++)//枚举当前行状态
{
if(s[i] & num[j].date) continue;//山地不能放
for(R k=;k<=tot;k++)//枚举上一行状态
{
if(s[i-] & num[k].date) continue;
if(num[j].date & num[k].date) continue;//不能在同一个位置有炮
for(R l=;l<=tot;l++)//枚举上上行状态
{
if(s[i-] & num[l].date) continue;
if((num[j].date & num[l].date) | (num[k].date & num[l].date)) continue;//都不能相互冲突
f[i][j][k]=max(f[i][j][k],f[i-][k][l] + num[j].one);
}
}
}
}
for(R i=;i<=tot;i++)//枚举最后一行的状态
for(R j=;j<=tot;j++)
{
if((s[n] & num[i].date) || (s[n-] & num[j].date)) continue;
ans=max(ans,f[n][i][j]);//是否冲突,,,就懒得判了吧,反正也是0
}
printf("%d\n",ans);
} int main()
{
// freopen("in.in","r",stdin);
pre();
work1();//先找到所有有效情况
work();
// fclose(stdin);
return ;
}

[NOI2001]炮兵阵地 状压DP的更多相关文章

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

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

  2. P2704 [NOI2001]炮兵阵地 (状压DP)

    题目: P2704 [NOI2001]炮兵阵地 解析: 和互不侵犯一样 就是多了一格 用\(f[i][j][k]\)表示第i行,上一行状态为\(j\),上上行状态为\(k\)的最多的可以放的炮兵 发现 ...

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

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

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

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

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

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

  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. 炮兵阵地 /// 状压DP oj26314

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

随机推荐

  1. mysql中的直方图采样逻辑

    int handler::sample_next(uchar *buf) { // Temporary set inited to RND, since we are calling rnd_next ...

  2. Mac环境下RabbitMq安装与测试教程

    RabbitMq安装与测试教程 Installing on Mac I. 安装 123456789 brew install rabbitmq ## 进入安装目录cd /usr/local/Cella ...

  3. Appium-测试失败后屏幕截图的

    本文参考:http://www.cnblogs.com/hexianl/p/4958556.html 使用testng测试框架进行管理测试 1.创建监听,代码如下: import io.appium. ...

  4. 韦大仙--简单的monkey测试命令行操作及生成log日志保存

    作中,在将apk交给软件测试人员去测试之前,不免要自己先自测,monkey自测是一个不错的选择! 步骤很简单: 1.测试用的手机与电脑连接好USB ,并且安装好驱动(我一般都是通过豌豆荚自动安装的)! ...

  5. tpo-09 C1 Advice on a term paper's topic

    第 1 段 1.Listen to a conversation between a student and her professor. 请听一段一名学生和教授讨论的对话. 第 2 段 1.Befo ...

  6. 自己来编写一份 Python 脚本 第一版

    解决问题 我们已经探索了 Python 语言中的许多部分,现在我们将通过设计并编写一款程序来了解如何把这些部分组合到一起.这些程序一定是能做到一些有用的事情.这节的Python教程就是教大家方法去学习 ...

  7. 关于javascript的一个小问题,请问有人看出啥问题吗?

    最近学习javascript,有一个问题挺奇怪的,先贴出代码: function binarySearch(){ var arr = [0,1,2,3]; var res = actbinarySea ...

  8. 【springmvc+mybatis项目实战】杰信商贸-1.项目背景

    1.项目背景杰信项目物流行业的项目,杰信商贸是国际物流行业一家专门从事进出口玻璃器皿贸易的公司.公司总部位于十一个朝代的帝王之都西安,业务遍及欧美.随着公司不断发展壮大,旧的信息系统已无法满足公司的快 ...

  9. poj 2155 (二维树状数组 区间修改 求某点值)

    Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 33682   Accepted: 12194 Descript ...

  10. 自测之Lesson8:进程操作

    题目:请解释wait是如何同步父子进程的. 程序代码: #include <stdio.h> #include <unistd.h> #include <sys/type ...