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

如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。 现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
输入输出格式
输入格式:
第一行包含两个由空格分割开的正整数,分别表示N和M;
接下来的N行,每一行含有连续的M个字符(‘P’或者‘H’),中间没有空格。按顺序表示地图中每一行的数据。N≤100;M≤10。
输出格式:
仅一行,包含一个整数K,表示最多能摆放的炮兵部队的数量。
输入输出样例
输入样例#1:
5 4
PHPP
PPHH
PPPP
PHPP
PHHP
输出样例#1:
6
真的很强了这个题
好好地理解了状压DP
预处理以下
1. 二进制数的1个数(统计答案)cnt数组
2. 二进制数两个1之间距离是否小于2(防止同一行打架)fight数组
3. 二进制数是否有1和输入的山对上(&结果为1) x&std_line[i]
cnt数组可以方便地由之前的状态转移,和之前的题一样的思路。
最初是三维状态f[i][j][k] 第i行 状态j 前一行状态k
然后枚举前一行和前前行的状态,转移,加上 cnt[这行状态]
但是100*1024*1024 显然炸了,转移时间1024*1024*1024*100 飞了
考虑对压缩的状态继续进行压缩(离散化?)
尝试输出了仅仅符合预处理2(同一行不打架的) 在m=10时也仅有60种放置方案
也就是说,二三维开60,对应到数组okset[i]j存储对应可用状态
可以用哨兵(okset[i][0])存储大小(类似vector.size()),不过我单独拿出来siz数组存了
毕竟,一堆堆方括号不好看(二维邻接表的教训)
这样空间绰绰有余(预处理3可能进一步减小数据量)
不过要注意的是边界问题,第1行单独拿出来处理(别忘了统计ans,否则若n==1就挂了)
f[1][i][1~60] 均为cnt[okset[1][i]]
//Stay foolish,stay hungry,stay young,stay simple
#include<iostream>
#include<vector>
#include<cstdio>
using namespace std;
const int MAXN=105,L=11;
int n,m;
bool map[MAXN][L];
int std_line[MAXN],fight[1026];
int cnt[1026];
int f[MAXN][61][61];
int okset[MAXN][61];
int siz[MAXN];
char s[L];
void debug(int x){
for(int i=10;i>=0;i--) {
cout<<((x>>i)&1);
}
cout<<endl;
}
int main(){
cin>>n>>m;
getchar();//
for(int i=1;i<=n;i++){
scanf("%s",s+1);
for(int j=1;j<=m;j++){
map[i][j]=s[j]-'P';
std_line[i]|=(map[i][j]<<(j-1));
}
}
for(int i=0;i<(1<<m);i++){
cnt[i]=cnt[i>>1]+(i&1);
int v=(i<<2);
int cnt0=0;
while(v){
if(v&1){
if(cnt0<2) {fight[i]=1; break;}
cnt0=0;
}else{cnt0++;}
v>>=1;
}
}
for(int i=1;i<=n;i++){
for(int j=0;j<(1<<m);j++){
if((j&std_line[i])==0&&!fight[j]) {
okset[i][++siz[i]]=j;
}
}
}
int ans=0;
for(int i=1;i<=siz[1];i++){
for(int j=1;j<=60;j++){
f[1][i][j]=cnt[okset[1][i]];
}
}
siz[0]=1;
for(int i=2;i<=n;i++){
for(int x=1;x<=siz[i];x++){
for(int y=1;y<=siz[i-1];y++){
for(int z=1;z<=siz[i-2];z++){
int j=okset[i][x],k=okset[i-1][y],l=okset[i-2][z];
if(((j&k)!=0)||((j&l)!=0)||((k&l)!=0)) continue;
// cout<<"ID:"<<i<<endl;
// debug(j);debug(k);debug(l);
// cout<<"F:";
f[i][x][y]=max(f[i][x][y],f[i-1][y][z]+cnt[j]);
// cout<<f[i][x][y]<<endl;
ans=max(ans,f[i][x][y]);
}
}
}
}
cout<<ans<<endl;
return 0;
}
[LUOGU] P2704 炮兵阵地的更多相关文章
- luogu P2704 炮兵阵地(经典状态压缩DP)
方格有m*n个格子,一共有2^(m+n)种排列,很显然不能使用暴力法,因而选用动态规划求解. 求解DP问题一般有3步,即定义出一个状态 求出状态转移方程 再用算法实现.多数DP题难youguan点在于 ...
- 【Luogu】P2704炮兵阵地(状压DP)
题目链接 话说还真没见过能影响两行的状压.想了半天想出来f数组再多一维就能表示,但是没想到怎么才能不爆空间…… 也是从这道题里学到的一个妙招. 可以把合法状态存到一个数组里,然后用数组下标来映射状态. ...
- P2704 炮兵阵地
题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图.在每一格平原地形上最 ...
- 洛谷P2704 炮兵阵地
本题过于经典...... 对于这种网格状压DP,套路一波刷表法DFS转移就没了. 三进制状压,0表示当前,上一个都没有.1表示当前无,上一个有.2表示当前有. 转移的条件就是上一行为0,当前不是山地, ...
- luogu 2704 炮兵阵地 状压dp
状压的基础题吧 第一次看感觉难上天,后来嘛就.. 套路:先根据自身状态筛出可行状态,再根据地图等其他限制条件筛选适合的状态加入答案 f i,j,k 分别代表 行数,本行状态,上行状态,再累加答案即可 ...
- 洛谷P2704 [NOI2001]炮兵阵地 [状压DP]
题目传送门 炮兵阵地 题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图 ...
- C++ 洛谷 P2704 [NOI2001]炮兵阵地
P2704 [NOI2001]炮兵阵地 没学状压DP的看一下 此题意思很简单,如下图,就是十字架上的不能有两个点放炮兵. 在做此题前,先做一下玉米田 玉米田题解 分析: 而m即一行的个数小于等于10, ...
- P2704 [NOI2001]炮兵阵地 (状压DP)
题目: P2704 [NOI2001]炮兵阵地 解析: 和互不侵犯一样 就是多了一格 用\(f[i][j][k]\)表示第i行,上一行状态为\(j\),上上行状态为\(k\)的最多的可以放的炮兵 发现 ...
- [洛谷P2704] [NOI2001]炮兵阵地
洛谷题目链接:[NOI2001]炮兵阵地 题目描述 司令部的将军们打算在NM的网格地图上部署他们的炮兵部队.一个NM的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示), ...
随机推荐
- vector中插入pair
我们知道map和multimap的作用,这两种数据类型在存储数据时,会根据pair<>的first成员进行排序,不同的时前者将不会插入对first成员重复的结构,后者可以.那如果我们只想存 ...
- BZOJ3834:Solar Panels (分块)
题意 询问两个区间[smin,smax],[wmin,smax]中是否存在k的倍数,使得k最大 分析 将其转化成\([\frac{smin-1}k,\frac{smax}k],[\frac{wmin- ...
- bzoj1725: [Usaco2006 Nov]Corn Fields牧场的安排(状压dfs)
1725: [Usaco2006 Nov]Corn Fields牧场的安排 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1122 Solved: 80 ...
- 图论之最短路算法之SPFA算法
SPFA(Shortest Path Faster Algorithm)算法,是一种求最短路的算法. SPFA的思路及写法和BFS有相同的地方,我就举一道例题(洛谷--P3371 [模板]单源最短路径 ...
- Luogu P2278 [HNOI2003]操作系统【优先队列/重载运算符/模拟】 By cellur925
题目传送门 本来是照着二叉堆的题去做的...没想到捡了个模拟...不过模拟我都不会...我好弱啊... 其实核心代码并不长,比辰哥的标程短到不知哪里去...但是思路需要清晰. 读题的时候我明白,当有优 ...
- April Fools Contest 2017 C
Description DO YOU EXPECT ME TO FIND THIS OUT? WHAT BASE AND/XOR LANGUAGE INCLUDES string? DON'T BYT ...
- LIS && LCS && LCIS && LPS && MCS模板
1. LIS (Longest Increasing Subsequence) O (n^2): /* LIS(Longest Increasing Subsequence) 最长上升子序列 O (n ...
- RHEL 6.5----rsync+inotify数据同步服务
Rsync特性: 可以镜像保存整个目录树和文件系统: 可以保持原文件的权限.时间.软硬链接等: 安装简单. 传输特点: 速度快:rsync首次同步会复制同步全部内容,以后只传输修改过的文件: 压缩传输 ...
- canvas 平移&缩放
1.平移 canvas其实只是一个包装器,真正起着重要作用的部分是2D渲染上下文,这才是我们真正绘制图形的地方. 然而2D渲染上下文是一种基于屏幕的标准绘制平台.它采用屏幕的笛卡尔坐标系统,以左上角( ...
- 【Laravel】 常用命令
自动创建项目 laravel new || laravel new xxx || composer create-project --prefer-dist laravel/laravel blog ...