https://www.luogu.org/problem/show?pid=2704

题意:

炮兵在地图上的摆放位子只能在平地('P')

炮兵可以攻击上下左右各两格的格子;

而高原('H')上炮兵能够攻击到但是不能摆放

求最多能摆放的炮兵的数量

就是这个意思。

难度提高,弱省省选

一开始是想写dfs(迷之八皇后)的,

但是看到数据量100就想dp了;

因为题目n的范围给的很少n<=10,想到状压

非常明显是一个状态压缩的dp(状压dp)

其实可以当做状压的入门题目来做。

由于本行的状态是由前若干行推出来的,所以想到了从上推到下(而不是从左推到右)

还有,本行的状态与前1行,前2行的状态密切相关的(炮兵不互相攻击)

写出我们dp的状态:f[i,r1j]表示当前第i行状态为j,i-1行状态为r1的炮兵数

转移其实就是非常简单了:(r2就是前第2行的状态)

f[i,r1,j]:=max(f[i,r1,j],f[i-1,r2,r1]+sum[j]);

转移的条件:r1和r2不与H有一个重合;r1和r2不能被互相打到或达j

本题主要难在处理dp初始化的方面;

首先我们需要保证每一种拓展出来的炮兵排列的方式需要在该行中横向不互相攻击;

这种每行不攻击的序列总数小于等于60;

pd函数非常好写:

function pd(x:longint):boolean;//判断此时放的是否合法(附近两位不能有1)
begin
if (x and (x<<))<> then exit(false);
if (x and (x<<))<> then exit(false);
exit(true);
end;

引入col[i]的二进制数组,表示第i行‘H’的分布 if s[j]='H' then col[i]:=col[i] or (1<<(j-1));

注意这里需要j-1,因为二进制是从2^0开始的。

注意初始化第0行所有地点都是高山,由于第0行可能会影响第2行;

特殊处理第一行:(st数组保存所有合法的序列,cnt为合法序列的个数,st标号1~cnt)

for i:= to cnt do begin
if (col[] and st[i])= then f[,,i]:=sum[i];
end;

所以,本题的代码简单,主要注意的是初始值和dp式不要写错(4维的转移,暴力)

uses math;
var n,m,i,j,r1,r2,ans,cnt:longint;
f:array[..,..,..]of longint;
//f[i,j,k]表示当前第i行状态为j,i-1行状态为k的炮兵数
s:string;
st,sum,col:array[..]of longint;
function pd(x:longint):boolean;//判断此时放的是否合法(附近两位不能有1)
begin
if (x and (x<<))<> then exit(false);
if (x and (x<<))<> then exit(false);
exit(true);
end;
function getbit(x:longint):longint;//求出二进制数x中有几个1
var sum:longint;
begin
sum:=;
while x> do begin
if (x and )= then inc(sum);
x:=x>>;
end;
exit(sum);
end;
procedure getdp(m:longint);
var e,i:longint;
begin
e:=<<m;
cnt:=;
for i:= to e- do
if pd(i) then begin
inc(cnt);
st[cnt]:=i; //保存此时的状态
sum[cnt]:=getbit(i); //炮兵的个数
end;
end;
begin
readln(n,m);
getdp(m);
fillchar(col,sizeof(col),);
for i:= to m do col[]:=col[] or (<<i);
for i:= to n do begin
readln(s);
for j:= to m do
if s[j]='H' then col[i]:=col[i] or (<<(j-));
end;
//col[i]表示第i行高地的分布
fillchar(f,sizeof(f),);//clear!
for i:= to cnt do begin
if (col[] and st[i])= then f[,,i]:=sum[i];
end;
for i:= to n do
for j:= to cnt do //现在这行的状态是j
if (col[i] and st[j])= then
for r1:= to cnt do //上一行状态是r1
if (st[j] and st[r1])= then
for r2:= to cnt do //上上行的状态是r2
if (st[j] and st[r2])= then
if f[i-,r2,r1]<>- then
f[i,r1,j]:=max(f[i,r1,j],f[i-,r2,r1]+sum[j]);
ans:=;
for i:= to cnt do
for j:= to cnt do
ans:=max(ans,f[n,i,j]);
writeln(ans);
end.

dp乱写1:状态压缩dp(状压dp)炮兵阵地的更多相关文章

  1. 状态压缩动态规划 状压DP

    总述 状态压缩动态规划,就是我们俗称的状压DP,是利用计算机二进制的性质来描述状态的一种DP方式 很多棋盘问题都运用到了状压,同时,状压也很经常和BFS及DP连用,例题里会给出介绍 有了状态,DP就比 ...

  2. 状态压缩动态规划(状压DP)详解

    0 引子 不要999,也不要888,只要288,只要288,状压DP带回家.你买不了上当,买不了欺骗.它可以当搜索,也可以卡常数,还可以装B,方式多样,随心搭配,自由多变,一定符合你的口味! 在计算机 ...

  3. hihoCoder 1044 : 状态压缩·一 状压dp

    思路:状态压缩,dp(i, j)表示考虑前i个数且[i-m+1, i]的选择情况为j.如果要选择当前这个数并且,数位1的个数不超过q,则dp[i+1][nex] = max(dp[i+1][nex], ...

  4. hihocoder #1044 : 状态压缩·一 状压DP

    http://hihocoder.com/problemset/problem/1044 可以看出来每一位的选取只与前m位有关,我们把每个位置起始的前m位选取状态看出01序列,就可以作为一个数字来存储 ...

  5. 【bzoj3195】【 [Jxoi2012]奇怪的道路】另类压缩的状压dp好题

    (上不了p站我要死了) 啊啊,其实想清楚了还是挺简单的. Description 小宇从历史书上了解到一个古老的文明.这个文明在各个方面高度发达,交通方面也不例外.考古学家已经知道,这个文明在全盛时期 ...

  6. 有关状压DP

    [以下内容仅为本人在学习中的所感所想,本人水平有限目前尚处学习阶段,如有错误及不妥之处还请各位大佬指正,请谅解,谢谢!] 引言 动态规划虽然已经是对暴力算法的优化,但在某些比较特别的情况下,可以通过一 ...

  7. 【状压DP】bzoj1087 互不侵犯king

    一.题目 Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上.下.左.右,以及左上.左下.右上.右下八个方向上附近的各一个格子,共8个格子. I ...

  8. 状压dp(总结)状态压缩

    状压这个和二进制分不开关系 所以,对于二进制的熟悉是必不可少的技能 &  与操作,1不变,0变0 |  或操作,0不变,1变1 ^  异或操作,0不变,1取反 - 取反操作,把每一个二进制位0 ...

  9. 状压DP学习笔记

    有的时候,我们会发现一些问题的状态很难直接用几个数表示,这个时候我们就会用到状压dp啦~~. 状压就是状态压缩,就是讲原本复杂难以描述的状态用一个数或者几个数来表示qwq.状态压缩是一个很常用的技巧, ...

  10. 互不侵犯_状压$dp$

    如果有想学习状压\(dp\)的童鞋,请光临博客状压\(dp\)初学 互不侵犯 题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八 ...

随机推荐

  1. [Deep-Learning-with-Python] Keras高级概念

    Keras API 目前为止,介绍的神经网络模型都是通过Sequential模型来实现的.Sequential模型假设神经网络模型只有一个输入一个输出,而且模型的网络层是线性堆叠在一起的. 这是一个经 ...

  2. mysql 配置 root 远程访问

    来源: https://www.cnblogs.com/24la/p/mariadb-remoting-access.html 首先配置允许访问的用户,采用授权的方式给用户权限 GRANT ALL P ...

  3. [LOJ#6033]. 「雅礼集训 2017 Day2」棋盘游戏[二分图博弈、匈牙利算法]

    题意 题目链接 分析 二分图博弈经典模型,首先将棋盘二分图染色. 考虑在某个最大匹配中: 如果存在完美匹配则先手必败,因为先手选定的任何一个起点都在完美匹配中,而后手则只需要走这个点的匹配点,然后先手 ...

  4. java批量爬取电影资源

    摘要 网上有很多个人站来分享电影资源,其实有时候我们自己也想做这个一个电影站来分享资源.但是这个时候就有一个问题,电影的资源应该从哪里来呢?难道要自己一条条手动去从网络上获取,这样无疑是缓慢而又效率低 ...

  5. 萌新程序媛的首个作品,基于NoSQL的内容管理及低码开发平台

    尽管入行有一段时间了,但之前还从来没想过要开发一款完整的软件产品.这个我跟朋友开发的第一款软件,希望大家帮我们多宣传推广.首个版本肯定有很多的不足,大家也给我们多提意见,还有很多规划中的功能要在之后的 ...

  6. linux centos 中Tomcat的安装和自启动配置

    Tomcat的安装和自启动配置将tomcat添加为linux系统服务,网上找到了很多方法,其中比较简单的如下:方法一:(亲测有效)1. 首先需要将$Tomcat_HOME/bin目录下的catalin ...

  7. jmeter的开启

    先申明我以jmeter的3.2版本来描述本文内容,通常不要选择太新的版本,因为新版本容易出现不稳定和不兼容因素.启动jmeter的前提是JDK已经安装和配置,具体的JDK已经安装和配置自行查资料,此处 ...

  8. Jenkins Maven安装设置

    Jenkins Maven安装设置 如果没有学习过 Maven 的朋友,可以先了解 Maven教程,然后再进一步学习本教程文章. 第1步:下载和设置Maven Maven的官方网站就是Apache M ...

  9. 华为笔试——C++字符串四则运算的实现

    题目:字符串四则运算的实现 有字符串表示的一个四则运算表达式,要求计算出该表达式的正确数值.四则运算即:加减乘除"+-*/",另外该表达式中的数字只能是1位(数值范围0~9),运算 ...

  10. PHP学习 Object Oriented 面向对象 OO

    定义类class class_name [extends partclass_name]{public private protected var property_name = value;publ ...