状态压缩动态规划(状压dp)
动态规划实际上就是重复使用历史记录。有时候在解决一个问题的时候,通常是将问题转化为一系列的子问题,子问题再转化为一些的子问题,这样就把大问题细化成了小问题,但是在所有的子问题中可能出现相同的子问题,于是动态规划就将每种的不同的子问题存储到表中,当再次遇到相同的子问题就从表中查找已存的历史记录即可,减少计算时间。把历史记录称作为状态。
通常用一位数组dp[]或者二维数组dp[][]甚至三维数组dp[][][]来保存历史记录(状态)。
有时候对于一些问题,其状态表示很复杂,需要较多内存保存一个状态。比如对于背包问题,每件物品可以选择放(1)与不放(0),假设三件物品,110这一状态表示第一、二件物品放。第三件物品不放。如果我们用一个变量表示一件物品放和不放,那么就需要使用三个变量或使用一个一维数组来表示这一状态,这样很占空间。
考虑没见物品只有放与不放两种情况,可以使用一个二进制位来表示,1表示放,0表示不放,那这样就只需要三个二进制位来表示一个状态,如果将每个状态的二进制数用十进制来表示,那么上述用一维数组表示的状态就可以用一个十进制数来表示,将一种状态的表示从使用一维数组降到只使用一个变量,即一个变量就能表示所有物品放与不放的一种状态,减少了空间的使用。对于n件物品,一共用2n种状态,压缩前需要2n个一维数组表示,压缩后只需要2n个变量表示。
上述就是状态压缩动态规划,它一类特殊的动态规划,简称状压DP,是利用计算机二进制的性质来描述状态的一种DP方式。通常使用一维变量来表示一个二进制状态。就是把原来需要使用一个布尔类型的数组来表示状态压缩到只需要使用一个int等类型的变量来表示状态。
对于一个十进制数,尽管没法访问其对应的二进制数中每一位的信息,但是可以使用位运算操作来得到每一个二进制位的信息。
比如判断一个十进制数x,它所对应的二进制数下第i位是不是等于1。
操作代码:if((x & (1<<(i−1)) == 1))