状态压缩动态规划【DP】

一、概述

1.状态压缩
状态压缩就是使用某种方法,简明扼要地以最小代价来表示某种状态,通常是用一串01数字(二进制数)来表示各个点的状态。这就要求使用状态压缩的对象的点的状态必须只有两种,0 或 1;当然如果有三种状态用三进制来表示也未尝不可。

2.使用条件
从状态压缩的特点来看,这个算法适用的题目符合以下的条件:

解法需要保存一定的状态数据(表示一种状态的一个数据值),每个状态数据通常情况下是可以通过2进制来表示的。这就要求状态数据的每个单元只有两种状态,比如说棋盘上的格子,放棋子或者不放,或者是硬币的正反两面。这样用0或者1来表示状态数据的每个单元,而整个状态数据就是一个一串0和1组成的二进制数。
解法需要将状态数据实现为一个基本数据类型,比如int,long等等,即所谓的状态压缩。状态压缩的目的一方面是缩小了数据存储的空间,另一方面是在状态对比和状态整体处理时能够提高效率。这样就要求状态数据中的单元个数不能太大,比如用int来表示一个状态的时候,状态的单元个数不能超过32(32位的机器),所以题目一般都是至少有一维的数据范围很小。
3.状压DP
状压DP,顾名思义,就是使用状态压缩的动态规划。

动态规划问题通常有两种,一种是对递归问题的记忆化求解,另一种是把大问题看作是多阶段的决策求解。这里用的便是后一种,这带来一个需求,即存储之前的状态,再由状态及状态对应的值推演出状态转移方程最终得到最优解。

二、位运算

一般基础的状压就是将一行的状态压成一个数,这个数的二进制形式反映了这一行的情况。由于使用二进制数来保存被压缩的状态,所以要用到神奇的二进制位运算操作,将一个十进制数转成二进制进行位运算操作再转回十进制数。

名称 运算符 Pascal样式 简记法则
按位与 & and 全一为一,否则为零
按位或 | or 有一位一,否则为零
按位取反 ~ not 是零则一,是一则零
按位异或 ^ xor 不同则一,相同则零
左移位 << shl a<<k等价于a*2^k
右移位 >> shr a>>k等价于a/2^k

注:在涉及到位运算时,一定要注意位运算的优先级。该加的括号一定要加

定义状态(例如) 求每一种放法的背包价值,状态应该是这n件物品的放与不放的情况。

最容易想到的是开个n维数组,第i个维度的下标如果是1的话代表放第i件物品,0的话代表不放第i件物品;

但是这样很容易造成空间浪费,而且多维数组也不好开;

我们仔细观察就会发现,每件物品有放与不放两种选择;假设我们有5件物品的时候,用1和0代表放和不放

如果这5件物品都不放的话,那就是00000;
如果这5件物品都放的话, 那就是11111;

看到这,我们知道可以用二进制表示所有物品的放与不放的情况;如果这些二进制用十进制表示的话就只有一个维度了。而且这一个维度能表示所有物品放与不放的情况;这个过程就叫做状态压缩;

注:先简单写一下 回头再改一下

posted @ 2021-08-16 18:09  snail灬  阅读(128)  评论(0编辑  收藏  举报