F - 炮兵阵地
来源:互联网 发布:linux命令 chm 编辑:程序博客网 时间:2024/06/03 09:53
F - 炮兵阵地
Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64uDescription
司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。
现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。
现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
Input
第一行包含两个由空格分割开的正整数,分别表示N和M;
接下来的N行,每一行含有连续的M个字符('P'或者'H'),中间没有空格。按顺序表示地图中每一行的数据。N <= 100;M <= 10。
接下来的N行,每一行含有连续的M个字符('P'或者'H'),中间没有空格。按顺序表示地图中每一行的数据。N <= 100;M <= 10。
Output
仅一行,包含一个整数K,表示最多能摆放的炮兵部队的数量。
Sample Input
5 4PHPPPPHHPPPPPHPPPHHP
Sample Output
6
这个状态压缩题感觉还是很有难度的,对于我们这种初学区间dp的人来说。通过这道题学长交给我们很多小知识点。用二进制数来存每个状态(1表示放一个炮台,0表示不放),一行有10个数,也就是说有2的10次方(1024)个状态,如果不提前处理那些限制条件,直接开一个dp[105][1050][1050]会超内存的,之前我就是这样超了,根据题意要先去掉存在相邻的1(11)和隔一个同为1(101)这样的状态,然后就会发现只剩下60种可能有效状态,因此开个dp[105][65][65]就足够了。
#include <iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int dp[106][65][65];int mm,sta[65],num[65],b[105];void init(int m){ for(int i=0;i<(1<<m);i++) { int x1=i<<1; //左移一位再与本身按位与可以去掉相邻的1这种状态 int x2=i<<2; //左移两位再与本身按位与可以去掉隔一个同为1的这种状态 if((x1&i)==0&&(x2&i)==0) sta[mm++]=i; //记录下每一个有效状态的二进制值 } memset(num,0,sizeof(num)); memset(b,0,sizeof(b)); for(int t=1;t<mm;t++) for(int i=0;i<m;i++) { int x3=1<<i; if((x3&sta[t])!=0) num[t]+=1; //对应的记录下每个有效状态中有多少个1 }}int main(){ char a[105][20]; int n,m; while(~scanf("%d%d",&n,&m)) { mm=0; init(m); for(int i=0;i<n;i++) { scanf("%s",a[i]); for(int j=0;j<m;j++) if(a[i][j]=='H') b[i]+=1<<j; //如果为H是不能放炮台的,所以记录下每一行的那些位置不能为1 } int ans=0; memset(dp,0,sizeof(dp)); for(int i=0;i<mm;i++) //预处理1,2行的dp值 for(int j=0;j<mm;j++) { if(!(b[0]&sta[i])) { dp[0][i][0]=num[i]; ans=max(ans,dp[0][i][0]); } if(!(b[1]&sta[j])&&!(sta[i]&sta[j])&&n>=2) //加上n>2这个条件是因为当n为1时输出的值不能被这个地方改变 { dp[1][j][i]=max(dp[1][j][i],num[j]+dp[0][i][0]); ans=max(ans,dp[1][j][i]); } } if(n<=2) { printf("%d\n",ans); continue; } for(int i=2;i<n;i++) for(int l=0;l<mm;l++) { for(int k=0;k<mm;k++) { for(int j=0;j<mm;j++) { if((b[i]&sta[j])==0&&!(sta[j]&sta[l])&&!(sta[j]&sta[k])&&!(sta[l]&sta[k]))//因为一个炮台的攻击范围是上下左右各两格,所以这里要判断当前行与上一行还有上上行三行之间不能存在相同位置为1 { dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+num[j]); ans=max(ans,dp[i][j][k]); } } } } printf("%d\n",ans); } return 0;}
0 0
- F - 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- pku1185炮兵阵地
- poj 1185 炮兵阵地
- POJ 1185 炮兵阵地
- 1185 炮兵阵地
- 炮兵阵地 POJ1185
- js的 function, javascript内置对象apply,call,this概念及之间的关系详解
- Spring 实现数据库读写分离
- Ubuntu下搭建web服务器
- Java实现Runnable接口方式实现多线程的优势
- iOS下载大型文件原理解析三
- F - 炮兵阵地
- windows7和linux共享文件
- Spark Sql性能测试及调优
- vim的基本使用
- 上传图片
- Java开发环境搭建
- linux下的find文件查找命令与grep文件内容查找命令
- Android Studio混淆相关
- linux下的cp和scp