题目:炮兵阵地

链接:http://poj.org/problem?id=1185

解题思路:

  首先用 int 来表示每一行的情况,比如说第一行是k1,那么【 k1&(k1>>2) | k1&(k1>>1) 】就可以排除一行中相邻的和隔一格的。。。

  地形也可以用 int (取反)来表示,比如说第一行是PPHPH,给他记作m1=00101(二进制数),1表示不能存放,那么对于一个数a,判断a是不是符合地形就可以用【 a & m1 】来表示,如果与出来的是真,那么说明存在某一位1&1的情景,就表示不符合。

  下一行是否能和上一行共存也用位运算来进行,比如下一行是s2,上一行是s1,那么【 s2 & s1 】为真就表示不能共存。

  上面是通过位运算来巧妙解决可行存放问题的方法。

  贴代码了:

  

 #include<stdio.h>
#include<string.h>
/*
改进。。。
*/
char s[][];
int mp[];
int ans[],ao;
int dp[][][];
/*
dp[i][j][k]: 第i行 - 上一行是ans[j]、本行是ans[k]的情况下,最多数量为多少。
因为有了两行的间隔,上面的炮台就不会影响到下面的,所以只要记录两行的所有情况,两行相同的可以计算出最大值了
*/
//因为列数最多为10,所以无视地形,一行最多有60中存放方式
void func(int m)
{
for(int i=;i<(<<m);i++)
{
if(i&(i>>)||i&(i>>)) continue;
ans[ao++]=i;
}
}
int count(int x)
{
int co=;
while(x)
{
co+=x&;
x>>=;
}
return co;
}
int pre[][],po,ko,lo;
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=;i<n;i++)
{
scanf("%s",s[i]);
}
memset(mp,,sizeof(mp));
for(int i=;i<n;i++)
{
for(int j=;j<m;j++)
{
if(s[i][j]=='H') mp[i]=mp[i]|(<<j);
}
}
ao=;
func(m);
memset(dp,,sizeof(dp));
po=;
for(int i=;i<ao;i++)
{
if(mp[]&ans[i]) continue;
int tmp=count(ans[i]);
dp[][][i]=tmp;
pre[][po++]=i; //记录第0行所有存值情况,po为总数
}
if(n==)
{
int mt=;
for(int i=;i<po;i++)
{
int line1=pre[][i]; //因为前面只有一行,所以只需要考虑pre[0][i]的情况
if(dp[][][line1]>mt) mt=dp[][][line1];
}
printf("%d\n",mt);
continue;
}
ko=;
for(int i=;i<po;i++)
{
for(int j=;j<ao;j++)
{
int line1=pre[][i];
if(ans[j]&mp[]) continue;
if(ans[line1]&ans[j]) continue;
int tmp=count(ans[j]);
dp[][line1][j]=dp[][][line1]+tmp;
pre[][ko]=line1; //到下一行时,这里就是上两行,下面的就是上一行,先用2暂存,最终再移入0
pre[][ko++]=j;
}
}
for(int i=;i<ko;i++)
pre[][i]=pre[][i];
bool v[][];
for(int i=;i<n;i++)
{
lo=;
memset(v,,sizeof(v));
for(int k=;k<ko;k++)
{
int line1=pre[i-][k],line2=pre[i-][k]; //上两行和上一行的情况
if(v[line1][line2]) continue; //因为有很多重复的,去重
v[line1][line2]=;
for(int u=;u<ao;u++)
{
if(ans[u]&mp[i]) continue; //如果与本身的地形不符,就跳过
if(ans[u]&ans[line1]||ans[u]&ans[line2]) continue; //如果和前两行矛盾就跳过
int tmp=count(ans[u]); //如果都满足条件,就计算这一行这种放法增加的数量
if(dp[i-][line1][line2]+tmp>dp[i][line2][u])
{
dp[i][line2][u]=dp[i-][line1][line2]+tmp;
pre[i+][lo]=line2; //先用i+1的存放,等k的循环结束再移到i-1
pre[i][lo++]=u;
}
}
}
for(int u=;u<lo;u++)
pre[i-][u]=pre[i+][u];
ko=lo;
}
int mt=;
for(int j=;j<ko;j++)
{
int line1=pre[n-][j],line2=pre[n-][j];
if(mt<dp[n-][line1][line2]) mt=dp[n-][line1][line2];
}
printf("%d\n",mt);
}
return ;
}

POJ_1185_炮兵阵地 dp+状态压缩的更多相关文章

  1. POJ1185炮兵阵地(DP状态压缩)

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

  2. POJ1185炮兵阵地(状态压缩DP)

    POJ飞翔.数据弱 ZQOJ飞翔 数据强 Description 司令部的将军们打算在N×M的网格地图上部署他们的炮兵部队.一个N×M的地图由N行M列组成,地图的每一格可能是山地(用"H&q ...

  3. luogu P2704 炮兵阵地(经典状态压缩DP)

    方格有m*n个格子,一共有2^(m+n)种排列,很显然不能使用暴力法,因而选用动态规划求解. 求解DP问题一般有3步,即定义出一个状态 求出状态转移方程 再用算法实现.多数DP题难youguan点在于 ...

  4. POJ 1185 炮兵阵地 (状态压缩DP)

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

  5. poj 1185 炮兵阵地 [经典状态压缩DP]

    题意:略. 思路:由于每个大炮射程为2,所以如果对每一行状态压缩的话,能对它造成影响的就是上面的两行. 这里用dp[row][state1][state2]表示第row行状态为state2,第row- ...

  6. 洛谷 P2704 [NOI2001]炮兵阵地 (状态压缩DP+优化)

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

  7. POJ 1185 炮兵阵地(状态压缩DP)

    题解:nState为状态数,state数组为可能的状态 代码: #include <map> #include <set> #include <list> #inc ...

  8. poj 1185 炮兵阵地(三维状态压缩dP)

    题目:http://poj.org/problem?id=1185 思路: d[i][j][k]表示第i行的状态为第k个状态,第i-1行的状态为第j个状态的时候 的炮的数量. 1表示放大炮, 地形状态 ...

  9. 【NOI2001】炮兵阵地(状态压缩,动态规划)

    题面 题面中有图片的存在,所以就贴个地址把 题解 简单题,,,, 原来一直觉得不会做... 现在发现是一道傻逼题 暴力压两行的状态 发现就需要滚一维. 然后暴力检查一下状态的可行性 DP检查MAX就可 ...

随机推荐

  1. Teradata数据库访问链条

  2. Win7 下安装ubuntu14.04双系统

    下面介绍一下利用wubi在Windows中安装Ubuntu 14.04的教程,或者说安装方法和注意事项.  方法一:直接下载wubi.exe 方法二:直接下载ubuntu-14.04-desktop- ...

  3. Django-rest-framework 接口实现 限制:(Throttle)

    限制:(Throttle) 主要用来限制 单独一个用户的 访问次数 自定义一个 限制类 创建一个Throttle.py(截流)文件 注意 一定要写两个方法 def allow_request(self ...

  4. springcloud(十五):Spring Cloud 终于按捺不住推出了自己的服务网关 Gateway

    Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gateway ,相比之前我们使用的 Zuul(1.x) 它有哪些优势呢?Zuul(1.x) 基于 Servlet,使 ...

  5. UltraISO制作Ubuntu14.04 64bit到U盘文件载入不完整

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/zinss26914/article/details/37728251 前言 今天新买的Thinkpa ...

  6. Unicode与UTF-8关系

    Unicode字符集合 Unicode 也称为 UCS(Universal Coded Character Set:国际编码字符集合) 是一个字符集合. 对世界上大部分的文字系统进行了整理,编码,使电 ...

  7. 编写第一个 Shell 脚本

    什么是 Shell 脚本? 一个 shell 脚本就是一个包含一系列命令的文件.shell 读取这个文件,然后执行 文件中的所有命令,就好像这些命令已经直接被输入到了命令行中一样. 怎样编写一个 Sh ...

  8. appium-基本操作的再次封装(加上文件路径、log、截图、异常处理)

    一:日志 二:文件路径 三:截图 四:异常处理(对基本操作,例如:等待元素出现.点击.按键灯进行封装.加上截图和日志记录)

  9. Spring Security(十一):4. Samples and Guides (Start Here)

    If you are looking to get started with Spring Security, the best place to start is our Sample Applic ...

  10. 初学Python——介绍一些内置方法

    1.abs()求绝对值 a=abs(-10) print(a) # 输出:10 2.all() 用来检测列表元素是否全部为空.0.False print(all([0,5,4])) #当列表所有元素都 ...