【题目描述】

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

如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。

现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。

【输入文件】

文件的第一行包含两个由空格分割开的正整数,分别表示N和M;

接下来的N行,每一行含有连续的M个字符(‘P’或者‘H’),中间没有空格。按顺序表示地图中每一行的数据。N≤100;M≤10。

【输出文件】

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

【分析】

这是一道经典的状态压缩类动态规划的题目。

我们可以看到表示列数的M(M<=10)很小,考虑用一个数的二进制位0与1来表示是否放置炮兵,同时我们用0来表示高低,1来表示平原,用map[i]来记录。

我们发现,因为炮兵的范围可以延伸到两行,所以我们在考虑L行的状态时,总要根据L-1行与L-2行来推得,于是,我们想到要先将所有可的状态通过枚举得出来(即满足同行两个炮兵互不攻击),并用state[i]来记录,同时我们也需要把每行所摆的炮兵数用Count[i]记录,注意第一行要特殊处理

完成了以上的准备工作,用F[i][J][k]来表示在第i行采用第j个状态,上一行采用第k个状态所能得到的最大炮兵数,于是我们很容易得到状态转移方程:

满足state[k1]&state[j]==0  &&  state[k2]&state[j]==0 && map[i]|state[j]==map[i]

f[i][j][k1]=max(f[i][j][k1],f[i-1][k1][k2]+Count[j])

需满足条件中三个条件所代表的意义分别是,I行与I-1行、I-2行均不冲突,且与地形不冲突,然后就可以转移状态了。

 #include <cstdlib>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
const int maxn=;
using namespace std;
int n,m,map[maxn],size;
int f[maxn][maxn][maxn];
int Count[maxn],state[maxn]; void prepare();
void dp(); int main()
{
int i,j;
//文件操作
freopen("cannon.in","r",stdin);
freopen("cannon.out","w",stdout); scanf("%d%d",&n,&m);
for( int i = ; i <= n; i ++ ){
char str[];
scanf("%s", str);
for( int j = ; j < m; j ++ ){
if( str[j] == 'P' )
map[i] = (map[i]<<)+;
else map[i] = (map[i]<<)+;
}
}
prepare();//预处理第一行
dp();//状态转移
int ans=;
for (i=;i<size;i++)
for (j=;j<size;j++)
ans=max(ans,f[n][i][j]); printf("%d\n",ans);
return ;
}
void prepare()
{
int i;//记录状态个数
memset(f,,sizeof(f)); for (i=;i<(<<m);i++)
{
//flag代表是否可以摆
int cnt=,temp=i,flag=;
while (temp>){
//摆了
if ((temp&)==){
if (flag>) break;
else flag=;//放上比较
cnt++;//用来统计本行放上的炮兵个数
}
else flag--;
temp=temp>>;
}
if (temp==)//可以摆
{
Count[size]=cnt;
//表示地形可以摆放
if ((map[]|i)==map[])
f[][size][]=cnt;
//累计状态
state[size++]=i;
}
}
return;
}
void dp()
{
int i,k1,k2,j;
for (i=;i<=n;i++)//决策行
for (k1=;k1<size;k1++)//上一行
for (k2=;k2<size;k2++)//上两行
if (f[i-][k1][k2]>)//上两行的摆放状态是合理的
{
for (j=;j<size;j++)
//查看当前摆放状态与上两行是否冲突
if ((state[k1]&state[j])== && (state[k2]&state[j])==)
if ((map[i]|state[j])==map[i])
f[i][j][k1]=max(f[i][j][k1],f[i-][k1][k2]+Count[j]);
}
}

【NOI2001】炮兵阵地的更多相关文章

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

    洛谷题目链接:[NOI2001]炮兵阵地 题目描述 司令部的将军们打算在NM的网格地图上部署他们的炮兵部队.一个NM的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示), ...

  2. C++ 洛谷 P2704 [NOI2001]炮兵阵地

    P2704 [NOI2001]炮兵阵地 没学状压DP的看一下 此题意思很简单,如下图,就是十字架上的不能有两个点放炮兵. 在做此题前,先做一下玉米田 玉米田题解 分析: 而m即一行的个数小于等于10, ...

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

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

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

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

  5. [Poj1185][Noi2001]炮兵阵地(状压dp)

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

  6. P2704 [NOI2001]炮兵阵地

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

  7. [NOI2001]炮兵阵地 【状压DP】

    #\(\color{red}{\mathcal{Description}}\) \(Link\) 司令部的将军们打算在\(N \times M\)的网格地图上部署他们的炮兵部队.一个\(N \time ...

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

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

  9. Luogu 2704 [NOI2001]炮兵阵地

    唔,想到了状压之后就不会了……实在是菜 考虑压两行,设$f_{i, j, k}$表示当前到第$i$行,上一行是$j$状态,前一行是$k$状态的最多能放的炮兵的数量. 发现第一维还可以滚掉,好像可以转移 ...

  10. 洛谷2704 [NOI2001]炮兵阵地

    题目戳这里 Solution 状压DP很好的入门题,用熟练位运算貌似也没那么难. 首先分析一下题目: 看见n=100,m=10,立马就想到了状压,看起来也像DP,所以我们还是采用行号为阶段的状压DP. ...

随机推荐

  1. 为什么我刚发表的文章变成了“待审核”,csdn有没有官方解释啊

    为什么我刚发表的文章变成了"待审核",csdn有没有官方解释啊,什么样的文章才会变为待审核呢? 并且从草稿箱和回收站里也看不到我的文章了,希望我的文章没有删掉. 文章的字是一个个打 ...

  2. EXE文件结构及读取方法

    一.EXE文件概念 EXE File英文全名executable file ,译作可运行文件,可移植可运行 (PE) 文件格式的文件,它能够载入到内存中,并由操作系统载入程序运行.是可在操作系统存储空 ...

  3. [MODx] 7. MIGX DB

    MODx provides a really unfriendly way to work with xPDO class. What I means is you need to define XM ...

  4. [AngularJS + cryptoJS + Gravatar] Provider vs factory

    Configurable Bits Need a Provider We want to be able to configure the characterLength before Tweetab ...

  5. LINUX系统备份

    LINUX系统备份 =========================================================== 作者: gswwgph(http://gswwgph.itp ...

  6. C#_MVC 自定义AuthorizeAttribute实现权限管理

    随笔- 28  文章- 31  评论- 16 MVC 自定义AuthorizeAttribute实现权限管理   在上一节中提到可以使用AuthorizeAttribute进行权限管理: [Autho ...

  7. View绘制详解(三),扒一扒View的测量过程

    所有东西都是难者不会,会者不难,Android开发中有很多小伙伴觉得自定义View和事件分发或者Binder机制等是难点,其实不然,如果静下心来花点时间把这几个技术点都研究一遍,你会发现其实这些东西都 ...

  8. swift 定义类方法(type methed)

    swift   中声明结构体或者枚举的类型方法,需要在func前加上关键字 ststic  ,但是如果要定义一个类的类方法时,需要用关键字 class class SomeClass { class ...

  9. Android_Notification

    xml文件: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns ...

  10. JAVA_JSON_example

    package cn.kjxy.JSON; import java.util.List; import org.json.JSONArray; import org.json.JSONExceptio ...