zoukankan      html  css  js  c++  java
  • [状压DP]

    总述

    状压 + DP = 状压DP

    状态压缩动态规划,就是我们俗称的状压DP,是利用计算机二进制的性质来描述状态的一种DP方式

    很多棋盘问题都运用到了状压,同时,状压也很经常和BFS及DP连用,例题里会给出介绍

    有了状态,DP就比较容易了

    举个例子:有一个大小为n*n的农田,我们可以在任意处种田,现在来描述一下某一行的某种状态:

    设n = 9;
    有二进制数 100011011(九位),每一位表示该农田是否被占用,1表示用了,0表示没用,这样一种状态就被我们表示出来了:见下表

    所以我们最多只需要 2n1 的十进制数就好(左边那个数的二进制形式是n个1)

    现在我们有了表示状态的方法,但心里也会有些不安:上面用十进制表示二进制的数,枚举了全部的状态,DP起来复杂度岂不是很大?没错,状压其实是一种很暴力的算法,因为他需要遍历每个状态,所以将会出现2^n的情况数量,不过这并不代表这种方法不适用:一些题目可以依照题意,排除不合法的方案,使一行的总方案数大大减少从而减少枚举

    位运算

    有了状态,我们就需要对状态进行操作或访问

    可是问题来了:我们没法对一个十进制下的信息访问其内部存储的二进制信息,怎么办呢?别忘了,操作系统是二进制的,编译器中同样存在一种运算符:位运算 能帮你解决这个问题

    为了更好的理解状压dp,首先介绍位运算相关的知识。

    1.’&’符号,x&y,会将两个十进制数在二进制下进行与运算,然后返回其十进制下的值。例如3(11)&2(10)=2(10)。

    2.’|’符号,x|y,会将两个十进制数在二进制下进行或运算,然后返回其十进制下的值。例如3(11)|2(10)=3(11)。

    3.’^’符号,x^y,会将两个十进制数在二进制下进行异或运算,然后返回其十进制下的值。例如3(11)^2(10)=1(01)。

    4.’<<’符号,左移操作,x<<2,将x在二进制下的每一位向左移动两位,最右边用0填充,x<<2相当于让x乘以4。相应的,’>>’是右移操作,x>>1相当于给x/2,去掉x二进制下的最有一位。

    这四种运算在状压dp中有着广泛的应用,常见的应用如下:

    1.判断一个数字x二进制下第i位是不是等于1。

    方法:if(((1<<(i1))&x)>0)if(((1<<(i−1))&x)>0)

    将1左移i-1位,相当于制造了一个只有第i位上是1,其他位上都是0的二进制数。然后与x做与运算,如果结果>0,说明x第i位上是1,反之则是0。

    2.将一个数字x二进制下第i位更改成1。

    方法:x=x|(1<<(i1))x=x|(1<<(i−1))

    证明方法与1类似,此处不再重复证明。

    3.把一个数字二进制下最靠右的第一个1去掉。

    方法:x=x&(x1)x=x&(x−1)

    感兴趣的读者可以自行证明。

  • 相关阅读:
    Socket和ServerSocket学习笔记
    跨域资源共享的10种方式
    javascript执行环境(执行期上下文)详解
    js 自动插入分号
    原型对象prototype和原型属性[[Prototype]]
    构造自己的动画函数:animation,stop功能的实现
    sizzle源码分析 (4)sizzle 技术总结及值得我们学习的地方
    sizzle源码分析 (3)sizzle 不能快速匹配时 选择器流程
    sizzle源码分析 (2)ID 类 tag querySelectorAll 快速匹配
    sizzle源码分析 (1)sizzle架构
  • 原文地址:https://www.cnblogs.com/-Wind-/p/10533447.html
Copyright © 2011-2022 走看看