状态压缩DP

题目

  1. POJ 棋盘问题
  2. POJ 炮兵阵地
  3. POJ Painting a Board
  4. POJ Relocation

思路

1. 状态压缩题目数据量在某一维度会比较小, 当看到二维数组的某一行或某一列比较短时, 就应该想到状态压缩. 一般来讲, 用 PUSH 操作更多

2. 第一题 棋盘问题. 每一行每一列只能放一个棋子. dp[i][state] 表示前 i 行放棋子后得到的状态为 state 时的方案数. dp[i][state] = sum(dp[i-1][oldstate])

3. 第二题 炮兵阵地. 每一行能够安放的炮台数是一定的. 一门大炮的攻击范围为 2, 所以状态需要记录前两行的. dp[i][s1][s2] 表示第 i 行安防炮台在 s1 处第 i-1 行安放炮台在 s2 处 时的总炮台数

dp[i][s1][s2] = funct(dp[i-1][s2][s3]) 其中 s1 和 s3 不能有交集

4. 第三题 涂色问题. N 不大于 15, 明显就是个状态压缩题. 状态 state 表示第 i 个方块有没有被涂色, 共有 (1<<15) 中可能性.

dp[state][i] 表示给第 i 个方块涂色后, 状态为 state 时的最小拿笔数

dp[newState][i] = min(dp[oldState][j] + 1) if color[j]  != color[i]

         = min(dp[oldState][j] )      if color[j] == color[i]

PUSH 更新, 合情合理

5. 第四题 搬家问题. 先计算所有的状态中能被两辆车一次搬走的集合. 对这些集合进行 01 背包

dp[i][state] 表示状态集中的前 i 个状态到达 state 时需要搬几次

dp[i][state] = dp[i-1][oldstate] + 1 其中 oldstate = state-state[i] (PULL 更新, 减法不易实现)

dp[i][s[i]|state] = dp[state] + 1

空间可以降低到一维

原文地址:https://www.cnblogs.com/zhouzhuo/p/3619036.html