[NOI2001]炮兵阵地
Description
司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示), 也可能是平原(用“P”表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队); 一支炮兵部队在地图上的攻击范围如图中黑色区域所示:
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。 图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。
现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内) ,在整个地图区域内最多能够摆放多少我军的炮兵部队。
Input
第一行包含两个由空格分割开的正整数,分别表示N和M; 接下来的N行,每一行含有连续的M个字符(‘P’或者‘H’),中间没有空格。按顺序表示地图中每一行的数据。 N≤100;M≤10。
Output
仅在第一行包含一个整数K,表示最多能摆放的炮兵部队的数量。
Sample Input
Sample Output
#include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <iostream> using namespace std; #define N 105 #define M 10005 int can[N],m,n; int f[M][N]; char S1[N]; int st[M]; int num2[M]; int judge1(int x) {if(x&(x<<1)){return 0;}if(x&(x<<2)){return 0;}return 1; } int judge2(int line,int x) {if(can[line]&st[x])return 0;return 1; } int same(int x,int z) {int S=st[x],s2=st[z];if((s2&S)==0){return 1;}return 0; } int num1(int x) {int cnt=0;for(int i=0;x!=0;i++){if(x&1){cnt++;}x=x>>1;}return cnt; } int main() {scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%s",S1);for(int j=1;j<=m;j++){if(S1[j-1]=='H'){can[i]=can[i]|(1<<(j-1));}}}int num=0;for(int i=1;i<(1<<m);i++){if(judge1(i)==1){num2[num]=num1(i);st[num++]=i;}}for(int i=0;i<=num;i++){if(judge2(1,i)==0)continue;f[i][1]=num2[i];}int ans=0;for(int S=0;S<num;S++){if(judge2(2,S)==0)continue;for(int s1=0;s1<num;s1++){if(judge2(1,s1)==0)continue;if(same(s1,S)==1){f[S][2]=max(num2[s1]+num2[S],f[S][2]);}}}for(int i=3;i<=n;i++){for(int S=0;S<num;S++){if(judge2(i,S)==0)continue;for(int s1=0;s1<num;s1++){if(judge2(i-1,s1)==0)continue;if(same(S,s1)==0)continue;for(int s2=0;s2<num;s2++){if(judge2(i-2,s2)==0)continue;if(same(s2,s1)==0)continue;if(same(S,s2)==1){f[S][i]=max(f[s2][i-2]+num2[s1]+num2[S],f[S][i]);ans=max(f[S][i],ans);}}}}}printf("%d\n",ans); }
View Code
后来我发现——
i-1可能和i-3冲突
所以还是改成3维了
dp[i][line][k]与f[k][line-1][l]有关
所以
#include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <iostream> using namespace std; #define N 105 #define M 1<<11 int can[N],m,n; int f[M][N][M]; char S1[N]; int st[M]; int num2[M]; int judge1(int x) {if(x&(x<<1)){return 0;}if(x&(x<<2)){return 0;}return 1; } int judge2(int line,int x) {if(can[line]&st[x])return 0;return 1; } int same(int x,int z) {int S=st[x],s2=st[z];if((s2&S)==0){return 1;}return 0; } int num1(int x) {int cnt=0;for(int i=0;i<=12;i++){if((x>>i)&1){cnt++;}}return cnt; } int main() {scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%s",S1);for(int j=1;j<=m;j++){if(S1[j-1]=='H'){can[i]=can[i]|(1<<(j-1));}}}int num=0;for(int i=0;i<(1<<m);i++){if(judge1(i)==1){num2[num]=num1(i);st[num++]=i;}}int ans=0;memset(f,-0x3f,sizeof(f));for(int i=0;i<num;i++){if(judge2(1,i)==0)continue;f[i][1][1]=num2[i];f[i][1][0]=num2[i];}for(int S=0;S<num;S++){if(judge2(2,S)==0)continue;for(int s1=0;s1<num;s1++){if(judge2(1,s1)==0)continue;if(same(s1,S)==1){f[S][2][s1]=max(f[s1][1][0]+num2[S],f[S][2][s1]);}}}for(int i=3;i<=n;i++){for(int S=0;S<num;S++){if(judge2(i,S)==0)continue;for(int s1=0;s1<num;s1++){if(judge2(i-1,s1)==0)continue;if(same(S,s1)==0)continue;for(int s2=0;s2<num;s2++){if(judge2(i-2,s2)==0)continue;if(same(s2,s1)==0)continue;if(same(S,s2)==1){f[S][i][s1]=max(f[s1][i-1][s2]+num2[S],f[S][i][s1]);}}}}}for(int i=0;i<num;i++){if(judge2(n,i)==0)continue;for(int j=0;j<num;j++){if(judge2(n-1,j)==0)continue;if(same(i,j)==0)continue;ans=max(ans,f[i][n][j]);}}printf("%d\n",ans); }
View Code
很好,这就A了么?
显然并没有
所以你可以考虑一下开小一点数组,比如你试试一行有多少种情况,据我所知那是小于100的
hhh
#include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <iostream> using namespace std; #define N 105 #define M 1<<11 int can[N],m,n; int f[N][N][N]; char S1[N]; int st[N]; int num2[M]; int judge1(int x) {if(x&(x<<1)){return 0;}if(x&(x<<2)){return 0;}return 1; } int judge2(int line,int x) {if(can[line]&st[x])return 0;return 1; } int same(int x,int z) {int S=st[x],s2=st[z];if((s2&S)==0){return 1;}return 0; } int num1(int x) {int cnt=0;for(int i=0;i<=12;i++){if((x>>i)&1){cnt++;}}return cnt; } int main() {scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%s",S1);for(int j=1;j<=m;j++){if(S1[j-1]=='H'){can[i]=can[i]|(1<<(j-1));}}}int num=0;for(int i=0;i<(1<<m);i++){if(judge1(i)==1){num2[num]=num1(i);st[num++]=i;}}int ans=0;memset(f,-0x3f,sizeof(f));for(int i=0;i<num;i++){if(judge2(1,i)==0)continue;f[i][1][1]=num2[i];f[i][1][0]=num2[i];}for(int S=0;S<num;S++){if(judge2(2,S)==0)continue;for(int s1=0;s1<num;s1++){if(judge2(1,s1)==0)continue;if(same(s1,S)==1){f[S][2][s1]=max(f[s1][1][0]+num2[S],f[S][2][s1]);}}}for(int i=3;i<=n;i++){for(int S=0;S<num;S++){if(judge2(i,S)==0)continue;for(int s1=0;s1<num;s1++){if(judge2(i-1,s1)==0)continue;if(same(S,s1)==0)continue;for(int s2=0;s2<num;s2++){if(judge2(i-2,s2)==0)continue;if(same(s2,s1)==0)continue;if(same(S,s2)==1){f[S][i][s1]=max(f[s1][i-1][s2]+num2[S],f[S][i][s1]);}}}}}for(int i=0;i<num;i++){if(judge2(n,i)==0)continue;for(int j=0;j<num;j++){if(judge2(n-1,j)==0)continue;if(same(i,j)==0)continue;ans=max(ans,f[i][n][j]);}}printf("%d\n",ans); }
很好,这就真的A了!
卡了我两天啊...
转载于:https://www.cnblogs.com/Winniechen/p/6910229.html
[NOI2001]炮兵阵地相关推荐
- C++ 洛谷 P2704 [NOI2001]炮兵阵地
P2704 [NOI2001]炮兵阵地 没学状压DP的看一下 此题意思很简单,如下图,就是十字架上的不能有两个点放炮兵. 在做此题前,先做一下玉米田 玉米田题解 分析: 而m即一行的个数小于等于10, ...
- 洛谷 P2704 [NOI2001]炮兵阵地
题目 题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P& ...
- 洛谷P2704 [NOI2001]炮兵阵地(状压dp)
题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P&quo ...
- 2022-5-20 吃月饼(something wrong), 数塔取数问题, 制铁棒, 子段统计, 炮兵阵地
1. 吃月饼 有一块月饼,是正三角形的,又被分割成了许多块小正三角形的月饼,里面有若干块被吃掉了.现在想要在这块月饼中再找一个由小正三角形月饼的正三角形月饼,而且要求面积最大的. 样例解释: 大月饼的 ...
- POJ 1185 炮兵阵地 (状压DP)
炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 14869 Accepted: 5575 Description ...
- hdu4539 郑厂长系列故事——排兵布阵 + POJ1158 炮兵阵地
题意: 郑厂长系列故事--排兵布阵 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Other ...
- poj 1185 NYOJ 85 炮兵阵地(状态压缩dp)
炮兵阵地 时间限制:2000 ms | 内存限制:65535 KB 难度:6 描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地 ...
- POJ1185 炮兵阵地 状压DP
炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 31819 Accepted: 12295 Descriptio ...
- 状压dp之二之三 炮兵阵地/玉米田 By cellur925
一.简单的状压dp 玉米田 题目描述 Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ ...
最新文章
- java中String,int,Integer,char、double类型转换
- HDU2021 发工资咯
- 【javascript】数字相加
- idea中git分支的使用
- 【转】GPS误差来源
- C#新手该如何规划学习【学习路线指南】
- hashmap大小_调整HashMap的大小:未来的危险
- OC语言中的便利初始化函数和便利构造器
- sql 大数据量插入优化
- IOS 内存优化和调试技巧
- spark sql 查看分区_Spark SQL解析查询parquet格式Hive表获取分区字段和查询条件
- JAVA在线编译,无需环境变量
- L1-063 吃鱼还是吃肉 (10 分)-PAT 团体程序设计天梯赛 GPLT
- Spark Accumulator累加器
- ps、ai、cdr2021平面设计三大软件的区别有哪些?
- 计算机408学什么区别,考研计算机408考什么
- JAVA8十大新特性详解
- python的指令大全_python列表命令
- 六款Win7系统可用的免费内存释放工具,让电脑跑的更high
- 使用Python实现Linux命令的批量执行
热门文章
- ElementUI el-table 在flex下的宽度自适应问题
- 【pwnable.tw】 death_note
- Centos7下使用yum安装lnmp zabbix3.2
- Property Exercise
- lenovo Think Centre TCM 开发环境搭建
- ASP.NET AJAX Preview 2
- android愤怒小鸟游戏、自定义View、掌上餐厅App、OpenGL自定义气泡、抖音电影滤镜效果等源码...
- NVIDIA | 一种重建照片的 AI 图像技术
- Linux集群服务 LVS
- 《中国人工智能学会通讯》——4.7 当前研究热点