POJ_1185_炮兵阵地 dp+状态压缩
题目:炮兵阵地
链接: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+状态压缩的更多相关文章
- POJ1185炮兵阵地(DP状态压缩)
问题描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P&quo ...
- POJ1185炮兵阵地(状态压缩DP)
POJ飞翔.数据弱 ZQOJ飞翔 数据强 Description 司令部的将军们打算在N×M的网格地图上部署他们的炮兵部队.一个N×M的地图由N行M列组成,地图的每一格可能是山地(用"H&q ...
- luogu P2704 炮兵阵地(经典状态压缩DP)
方格有m*n个格子,一共有2^(m+n)种排列,很显然不能使用暴力法,因而选用动态规划求解. 求解DP问题一般有3步,即定义出一个状态 求出状态转移方程 再用算法实现.多数DP题难youguan点在于 ...
- POJ 1185 炮兵阵地 (状态压缩DP)
题目链接 Description 司令部的将军们打算在NM的网格地图上部署他们的炮兵部队.一个NM的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用& ...
- poj 1185 炮兵阵地 [经典状态压缩DP]
题意:略. 思路:由于每个大炮射程为2,所以如果对每一行状态压缩的话,能对它造成影响的就是上面的两行. 这里用dp[row][state1][state2]表示第row行状态为state2,第row- ...
- 洛谷 P2704 [NOI2001]炮兵阵地 (状态压缩DP+优化)
题目描述 司令部的将军们打算在NM的网格地图上部署他们的炮兵部队.一个NM的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P" ...
- POJ 1185 炮兵阵地(状态压缩DP)
题解:nState为状态数,state数组为可能的状态 代码: #include <map> #include <set> #include <list> #inc ...
- poj 1185 炮兵阵地(三维状态压缩dP)
题目:http://poj.org/problem?id=1185 思路: d[i][j][k]表示第i行的状态为第k个状态,第i-1行的状态为第j个状态的时候 的炮的数量. 1表示放大炮, 地形状态 ...
- 【NOI2001】炮兵阵地(状态压缩,动态规划)
题面 题面中有图片的存在,所以就贴个地址把 题解 简单题,,,, 原来一直觉得不会做... 现在发现是一道傻逼题 暴力压两行的状态 发现就需要滚一维. 然后暴力检查一下状态的可行性 DP检查MAX就可 ...
随机推荐
- 高可用,完全分布式Hadoop集群HDFS和MapReduce安装配置指南
原文:http://my.oschina.net/wstone/blog/365010#OSC_h3_13 (WJW)高可用,完全分布式Hadoop集群HDFS和MapReduce安装配置指南 [X] ...
- js刷新页面的几种方式与区别
Javascript刷新页面的几种方法:1 history.go(0) 2 location.reload() 3 location=location 4 location.assign(locati ...
- mysql数据权限的分配
在我们使用mysql数据库时,有时我们的程序与数据库不在同一机器上,这时我们需要远程访问数据库.缺省状态下,mysql的用户没有远程访问的权限. 下面介绍两种方法,解决这一问题. 1.改表法 可能是你 ...
- Java 8 新特性:2-消费者(Consumer)接口
(原) 在上一篇,用到过这样一个方法: list.forEach(new Consumer<Integer>() { @Override public void accept(Intege ...
- centos7下安装docker(15.4跨主机网络-flannel)
flannel是CoreOS开发的容器网络解决方案,flannel为每一个host分配一个subnet,容器从这些subnet中分配IP,这些IP可以在host之间路由,容器无需NAT和port ma ...
- [JXOI2018]排序问题
嘟嘟嘟 这是今天做的第二道九条可怜的题,现在对他的题的印象是:表面清真可做,实则毒瘤坑人. 首先要感谢吉司机,我期望学的特烂,好在样例直接告诉我们期望怎么求了. 令\(b_i\)表示第\(i\)个不同 ...
- 转://创建oracle索引时需要注意的7个事项
在创建Oracle索引时,有一些问题使我们需要注意的,下面就为您介绍创建oracle索引的一些注意事项,希望对您学习创建Oracle索引方面能有所帮助. 1.一般来说,不需要为比较小的表创建索引: 2 ...
- PHP删除数组中空值的方法介绍
这篇文章主要介绍了PHP删除数组中空值的方法介绍,需要的朋友可以参考下 说来惭愧,以前在去掉数组的空值是都是强写foreach或者while的,利用这两个语法结构来删除数组中的空元素,简单代码如下: ...
- koa-convert源码分析
koa-convert最主要的作用是:将koa1包中使用的Generator函数转换成Koa2中的async函数.更准确的说是将Generator函数转换成使用co包装成的Promise对象.然后执行 ...
- 【Codeforces 212E】Restaurants
Codeforces 212 E 题意:给一棵树,其中删去一个点,剩余的联通块们同一个联通块都得涂同一个颜色(黑或白),问黑色涂的个数有可能是哪些. 思路:肯定是背包. 假设现在删掉\(u\)这个节点 ...