[NOI2001] 炮兵阵地
题目
Description
司令部的将军们打算在 N×MN×M 的网格地图上部署他们的炮兵部队。
一个 N×MN×M 的地图由 NN 行 MM 列组成,地图的每一格可能是山地(用 HH 表示),也可能是平原(用 PP 表示),如下图。
在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。
图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。
现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
1≤N≤100,1≤M≤10
Input
第一行包含两个由空格分割开的正整数,分别表示 NN 和 MM。
接下来的 NN 行,每一行含有连续的 MM 个字符,按顺序表示地图中每一行的数据。
Output
一行一个整数,表示最多能摆放的炮兵部队的数量。
Sample Input
5 4 PHPP PPHH PPPP PHPP PHHP
Sample Output
6
思路
一道状压的题;
枚举当前行和上两行的状态,并保证炮兵不能互相攻击即可;
状态转移方程就为
为第行状态,为第行的状态,为第行状态,为第行炮兵个数;
不过要注意的是最大范围是,三个枚举状态的循环会超时;
所以需要提前把满足条件的行预处理到一个数组,再枚举数组即可;
这样每个循环次数可以降到次以下,是不会超时的;
代码
#include<bits/stdc++.h> typedef long long ll; using namespace std; ll n,m; ll tot; ll a[1<<10],c[101][11]; ll dp[101][1<<6][1<<6]; int main() { scanf("%lld%lld",&n,&m); for(ll i=1;i<=n;i++) for(ll j=1;j<=m;j++) { char cc; cin>>cc; if(cc=='P') c[i][j]=1; } for(ll x=0;x<=(1<<m)-1;x++) { if(x&(x<<1)||x&(x<<2)) continue; a[++tot]=x;//预处理满足条件的行 } for(ll i=1;i<=n;i++) for(ll x=1;x<=tot;x++) { ll flag=0; for(ll j=1;j<=m;j++) if(c[i][j]==0&&a[x]&(1<<(j-1)))//如果是山地,就不能放炮兵 { flag=1; break; } if(flag) continue; ll sum=0; for(ll j=1;j<=m;j++) if(a[x]&(1<<(j-1))) sum++;//记录当前行炮兵数量 for(ll y=1;y<=tot;y++) for(ll z=1;z<=tot;z++) { if(a[x]&a[y]||a[x]&a[z]) continue;//保证与上两行互不攻击 dp[i][x][y]=max(dp[i][x][y],dp[i-1][y][z]+sum);//求最大数量 } } ll ans=0; for(ll x=1;x<=tot;x++) for(ll y=1;y<=tot;y++) ans=max(ans,dp[n][x][y]); printf("%lld",ans); return 0; }
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
分类:
题目来源---NOI
, dp--状压dp
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现