Description

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

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

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

Input

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

Output

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

Sample Input

5 4 PHPP PPHH PPPP PHPP PHHP

Sample Output

6
一开始我是2维的dp

#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]炮兵阵地相关推荐

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

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

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

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

  3. 洛谷P2704 [NOI2001]炮兵阵地(状压dp)

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

  4. 2022-5-20 吃月饼(something wrong), 数塔取数问题, 制铁棒, 子段统计, 炮兵阵地

    1. 吃月饼 有一块月饼,是正三角形的,又被分割成了许多块小正三角形的月饼,里面有若干块被吃掉了.现在想要在这块月饼中再找一个由小正三角形月饼的正三角形月饼,而且要求面积最大的. 样例解释: 大月饼的 ...

  5. POJ 1185 炮兵阵地 (状压DP)

    炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 14869   Accepted: 5575 Description ...

  6. hdu4539 郑厂长系列故事——排兵布阵 + POJ1158 炮兵阵地

    题意: 郑厂长系列故事--排兵布阵 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Other ...

  7. poj 1185 NYOJ 85 炮兵阵地(状态压缩dp)

    炮兵阵地 时间限制:2000 ms  |  内存限制:65535 KB 难度:6 描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地 ...

  8. POJ1185 炮兵阵地 状压DP

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

  9. 状压dp之二之三 炮兵阵地/玉米田 By cellur925

    一.简单的状压dp 玉米田 题目描述 Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ ...

最新文章

  1. java中String,int,Integer,char、double类型转换
  2. HDU2021 发工资咯
  3. 【javascript】数字相加
  4. idea中git分支的使用
  5. 【转】GPS误差来源
  6. C#新手该如何规划学习【学习路线指南】
  7. hashmap大小_调整HashMap的大小:未来的危险
  8. OC语言中的便利初始化函数和便利构造器
  9. sql 大数据量插入优化
  10. IOS 内存优化和调试技巧
  11. spark sql 查看分区_Spark SQL解析查询parquet格式Hive表获取分区字段和查询条件
  12. JAVA在线编译,无需环境变量
  13. L1-063 吃鱼还是吃肉 (10 分)-PAT 团体程序设计天梯赛 GPLT
  14. Spark Accumulator累加器
  15. ps、ai、cdr2021平面设计三大软件的区别有哪些?
  16. 计算机408学什么区别,考研计算机408考什么
  17. JAVA8十大新特性详解
  18. python的指令大全_python列表命令
  19. 六款Win7系统可用的免费内存释放工具,让电脑跑的更high
  20. 使用Python实现Linux命令的批量执行

热门文章

  1. ElementUI el-table 在flex下的宽度自适应问题
  2. 【pwnable.tw】 death_note
  3. Centos7下使用yum安装lnmp zabbix3.2
  4. Property Exercise
  5. lenovo Think Centre TCM 开发环境搭建
  6. ASP.NET AJAX Preview 2
  7. android愤怒小鸟游戏、自定义View、掌上餐厅App、OpenGL自定义气泡、抖音电影滤镜效果等源码...
  8. NVIDIA | 一种重建照片的 AI 图像技术
  9. Linux集群服务 LVS
  10. 《中国人工智能学会通讯》——4.7 当前研究热点