【NOI2001】炮兵阵地
【题目描述】
司令部的将军们打算在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】炮兵阵地的更多相关文章
- [洛谷P2704] [NOI2001]炮兵阵地
洛谷题目链接:[NOI2001]炮兵阵地 题目描述 司令部的将军们打算在NM的网格地图上部署他们的炮兵部队.一个NM的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示), ...
- C++ 洛谷 P2704 [NOI2001]炮兵阵地
P2704 [NOI2001]炮兵阵地 没学状压DP的看一下 此题意思很简单,如下图,就是十字架上的不能有两个点放炮兵. 在做此题前,先做一下玉米田 玉米田题解 分析: 而m即一行的个数小于等于10, ...
- P2704 [NOI2001]炮兵阵地 (状压DP)
题目: P2704 [NOI2001]炮兵阵地 解析: 和互不侵犯一样 就是多了一格 用\(f[i][j][k]\)表示第i行,上一行状态为\(j\),上上行状态为\(k\)的最多的可以放的炮兵 发现 ...
- 洛谷P2704 [NOI2001]炮兵阵地 [状压DP]
题目传送门 炮兵阵地 题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图 ...
- [Poj1185][Noi2001]炮兵阵地(状压dp)
炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 29476 Accepted: 11411 Descriptio ...
- P2704 [NOI2001]炮兵阵地
题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图.在每一格平原地形上最 ...
- [NOI2001]炮兵阵地 【状压DP】
#\(\color{red}{\mathcal{Description}}\) \(Link\) 司令部的将军们打算在\(N \times M\)的网格地图上部署他们的炮兵部队.一个\(N \time ...
- [NOI2001]炮兵阵地 状压DP
题面: 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图.在每一格平原地形上最多 ...
- Luogu 2704 [NOI2001]炮兵阵地
唔,想到了状压之后就不会了……实在是菜 考虑压两行,设$f_{i, j, k}$表示当前到第$i$行,上一行是$j$状态,前一行是$k$状态的最多能放的炮兵的数量. 发现第一维还可以滚掉,好像可以转移 ...
- 洛谷2704 [NOI2001]炮兵阵地
题目戳这里 Solution 状压DP很好的入门题,用熟练位运算貌似也没那么难. 首先分析一下题目: 看见n=100,m=10,立马就想到了状压,看起来也像DP,所以我们还是采用行号为阶段的状压DP. ...
随机推荐
- java的socket 编程
之前在学校的时候,有时间但是总是学不进去,现在工作了,总想多学点东西,但是又是没有时间来学习,只能在工作的闲暇之余,给自己充充电,随着学习的深入,越来月发现Java真的很强大,几乎什么都可以做的,以下 ...
- Volley使用指南第一回(来自developer.android)
最近闲来想看看android网络方面的东西.google在2013年发布了一个叫做Volley的网络请求框架,我看了一下官网,居然在training里面就有教程.首先,英文的东西看着 还是挺不爽的,特 ...
- CentOS 6.5 下载地址
CentOS 6.5 主要改动 Precision Time Protocol(精确时间协议)—— 原先是项技术预览 —— 现在已获全面支持.以下驱动程序支持网络时间戳印:bnx2x.tg3.e100 ...
- btrace拓展工具-java应用性能诊断优化利器
Btrace是一个实时监控工具,可以无需修改应用代码(事实上它修改了字节码),来达到不可告人的秘密!这是性能调优和诊断的利器! 它可以获取应用程序代码的执行时间,他可以让你无需修改代码,帮你做时间的打 ...
- 使用openssl库实现des,3des加密
原文地址: 使用openssl库实现des,3des加密 主要是调整了一下格式,以及一些变量的类型,以解决在VC2008下无法编译通过的问题. #include <stdio.h> #in ...
- iOS开发——开发技巧&Mac常用命令
现实和隐藏文件拓展名 显示:defaults write com.apple.finder AppleShowAllFiles Yes && killall Finder 隐藏:def ...
- iOS开发——swift精讲&MVC应用实战
MVC应用实战 iOS开发中设计模式是很重要的,其中,使用最多的就是MVC模式,今天就简单介绍一下在Swift中这么使用MVC模式来实现我们想要的功能: 模型-视图-控制器(Model-View-Co ...
- Spring MVC page render时jsp中元素相对路径的解决办法
前段时间做了用Spring Security实现的登录和访问权限控制的功能,但是page render使用的是InternalResourceResolver,即在spring的servlet配置文件 ...
- android学习日记13--数据存储之File存储
4.文件存储File File即传统的I/O 流存储文件,Activity提供了openFileOutput()方法可以用于把数据输出到文件中,具体的实现过程与在J2SE环境中保存数据到文件中是一样的 ...
- com.classpath.www
package com.classpath.www; import java.io.File; import java.net.URL; import javax.servlet.ServletCon ...