一、状态压缩
从状态压缩的特点来看,这个算法适用的题目符合以下的条件:
1.解法需要保存一定的状态数据(表示一种状态的一个数据值) ,每个状态数据通常情况下是可以通过 2 进制来表示的。这就要求状态数据的每个单元只有两种状态,比如说棋盘上的格子,放棋子或者不放,或者是硬币的正反两面。这样用 0 或者 1 来表示状态数据的每个单元,而整个状态数据就是一个一串 0 和 1 组成的二进制数。2.解法需要将状态数据实现为一个基本数据类型,比如 int, long 等等, 即所谓的状态压缩。状态压缩的目的一方面是缩小了数据存储的空间,另一方面是在状态对比和状态整体处理时能够提高效率。这样就要求状态数据中的单元个数不能太大,比如用 int 来表示一个状态的时候,状态的单元个数不能超过 32(32 位的机器)。
二、动态规划
如果说状态压缩是数据结构的话,那么动态规划应该是算法了。题目通过动态规划来解通常有两个动机,第一是利用递归的重叠子问题,进行记忆话求解,即递归法的优化。第二是把问题看作多阶段决策的过程来求解问题。在状态压缩动态规划中我们讨论的是第二种动机。
多阶段决策过程求解问题的动态规划最重要的是划分阶段和找到状态转移方程。 对于划分阶段,是根据不同阶段之间的独立性来划分,通常会用状态数组的第一个下标来记录这个阶段的标记(比如 01 背包问题中的状态数组第一个下标为物品的个数,棋盘放棋子问题中的状态数组的第一个下标为棋盘的行数等等)。另一个重要的便是状态转移方程,状态转移方程是递推时得到一个状态数据的重要根据。通常情况下状态数组的除了第一个下标以外都是表示状态数据的,而状态数组的值是和所求结果紧密结合的。在后面的几个例题中会重点说明
状态转移方程。