题目:炮兵阵地

链接: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. HTTP Health Checks

    This article describes how to configure and use HTTP health checks in NGINX Plus and open source NGI ...

  2. 【ZJOI2017】仙人掌

    [ZJOI2017]仙人掌 参考博客:https://www.cnblogs.com/wfj2048/p/6636028.html 我们先求出\(dfs\)树(就是\(dfs\)一遍),然后问题就变成 ...

  3. Django-rest-framework 接口实现 认证:(auth | authentication)

    认证:(auth | authentication) REST framework提供了一些开箱即用的身份验证方案,并且还允许你实现自定义方案. 在 rest_framework.authentica ...

  4. P1145 约瑟夫 W(模拟)

    暴力+模拟 #include<iostream> #include<cstring> using namespace std; int ans, k, k2; ]; bool ...

  5. 第9章 Java中的线程池 第10章 Exector框架

    与新建线程池相比线程池的优点 线程池的分类 ThreadPoolExector参数.执行过程.存储方式 阻塞队列 拒绝策略 10.1 Exector框架简介 10.1.1 Executor框架的两级调 ...

  6. 爬取伯乐在线文章(四)将爬取结果保存到MySQL

    Item Pipeline 当Item在Spider中被收集之后,它将会被传递到Item Pipeline,这些Item Pipeline组件按定义的顺序处理Item. 每个Item Pipeline ...

  7. linux命令之netstat

    功能:打印网络连接.路由表.接口统计信息.伪装连接和多播成员 参数 -r 显示路由表 -i 显示接口表 -n 不解析名字 -p 显示程序名 PID/Program -l 显示监听的 socket -a ...

  8. shell笔记-常用

    shell提取文件名: http://blog.csdn.net/u011544778/article/details/50773053 一.使用${} 1.${var##*/}该命令的作用是去掉变量 ...

  9. linux使用.net core 创建简单的MVC

    1 创建MVC 2.修改默认绑定的端口方法 ,在Program.cs 的Build之前加入 .UseUrls("http://*:8888")

  10. Generative Adversarial Nets[Pre-WGAN]

    本文来自<towards principled methods for training generative adversarial networks>,时间线为2017年1月,第一作者 ...