题目:炮兵阵地

链接: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. 为什么二流程序员都喜欢黑php?

    为什么二流程序员都喜欢黑php? 为什么程序员都喜欢黑php?这个嘛!你骂一句php是垃圾试试,保准php程序员不揍扁你!这就好像自己的母校,纵然有很多不好的地方,但是只允许自己调侃,不允许外人骂半句 ...

  2. UVA1471-Defense Lines(思维+STL)

    Problem UVA1471-Defense Lines Accept: 297  Submit: 2776Time Limit: 9000 mSec Problem Description Aft ...

  3. 【vue】vue +element 搭建项目,组件之间通信

    父子组件通信 父 通过props属性给 子传递数据 子 操作 父  this.$parent.XXX 子通过$emit传递参数 或者通过vue-bus vue-bus既可以实现父子组件之间的通信,也可 ...

  4. 【移动端】移动端字体单位font-size选择px还是rem

    对于只需要适配少部分手机设备,且分辨率对页面影响不大的,使用px即可对于需要适配各种移动设备,使用rem,例如只需要适配iphone和iPad等分辨率差别比较挺大的设备 html{font-size: ...

  5. day05 数据基本类型及内置方法:字符串str、列表list

    一:可变不可变类型 1.可变类型 值改变,id不变,说明是直接改变原值,是可变类型 2.不可变类型 值改变,id也跟着改变,说明是产生了新的值,是不可变类型 二:数字类型 1.整型Int 用途: 记录 ...

  6. 0、原生jdbc工厂类

    一.代码结构 二.JDBCFactory.java package com.test; import java.io.IOException; import java.io.InputStream; ...

  7. Debian系统下实现通过wpa_config连接WPA-PSK加密的Wifi连接

    Debian系统下实现通过wpa_config连接WPA-PSK加密的Wifi连接 文章参考:BASST | BLOG : Setting up Wifi - Debian Wheezy 预环境 De ...

  8. k8s 节点的 NodeAffinity 使用

    apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 kind: Deployment metadata: name: vi ...

  9. php 数组元素快速去重

    1.使用array_unique方法进行去重 对数组元素进行去重,我们一般会使用array_unique方法,使用这个方法可以把数组中的元素去重. <?php $arr = array(,,,, ...

  10. git 忽略无效解决办法

    有时候发现git提交了一些我们不需要提交的内容,这时候第一反应是加个忽略: https://github.com/github/gitignore 宇宙神器VS: https://github.com ...