状态压缩ppt课件

上传人:资****亨 文档编号:130807184 上传时间:2020-05-01 格式:PPT 页数:56 大小:437.50KB
返回 下载 相关 举报
状态压缩ppt课件_第1页
第1页 / 共56页
状态压缩ppt课件_第2页
第2页 / 共56页
状态压缩ppt课件_第3页
第3页 / 共56页
状态压缩ppt课件_第4页
第4页 / 共56页
状态压缩ppt课件_第5页
第5页 / 共56页
点击查看更多>>
资源描述

《状态压缩ppt课件》由会员分享,可在线阅读,更多相关《状态压缩ppt课件(56页珍藏版)》请在金锄头文库上搜索。

1、状态压缩 主讲 ftfish 周伟天津大学2007级 邮箱 ftfish zhouwei 手机 13752131713QQ 155175157 状态压缩 信息学发展势头迅猛 信息学奥赛的题目来源遍及各行各业 经常有一些在实际应用中很有价值的问题被引入信息学并得到有效解决 然而有一些问题却被认为很可能不存在有效的 多项式级的 算法 这里以对几个例题的剖析 简述状态压缩思想及其应用 状态压缩 预备知识 作为对下文的准备 这里先为使用Pascal的OIers简要介绍一下C C 样式的位运算 bitwiseoperation 其优先级 not and xor or 状态压缩 预备知识 位运算的特殊应用

2、and 用以取出一个数的某些二进制位取出一个数二进制中的最后一个1 lowbit x将一个数的某些位取反 状态压缩 引例 在n n n 20 的方格棋盘上放置n个车 可以攻击所在行 列 求使它们不能互相攻击的方案总数 10秒时间思考 状态压缩 引例 这个题目之所以是作为引例而不是例题 是因为它实在是个非常简单的组合学问题我们一行一行放置 则第一行有n种选择 第二行n 1 最后一行只有1种选择 根据乘法原理 答案就是n 这里既然以它作为状态压缩的引例 当然不会是为了介绍组合数学 我们下面来看另外一种解法 状态压缩递推 StatesCompressingRecursion SCR 状态压缩 引例解

3、法 我们仍然一行一行放置 取棋子的放置情况作为状态 某一列如果已经放置棋子则为1 否则为0 这样 一个状态就可以用一个最多20位的二进制数表示 例如n 5 第1 3 4列已经放置 则这个状态可以表示为01101 从右到左 设fs为达到状态s的方案数 则可以尝试建立f的递推关系 状态压缩 引例解法 考虑n 5 s 01101因为我们是一行一行放置的 所以当达到s时已经放到了第三行 又因为一行能且仅能放置一个车 所以我们知道状态s一定来自 状态压缩 引例解法 前两行在第3 4列放置了棋子 不考虑顺序 下同 第三行在第1列放置 前两行在第1 4列放置了棋子 第三行在第3列放置 前两行在第1 3列放置

4、了棋子 第三行在第4列放置 状态压缩 引例解法 这三种情况互不相交 且只可能有这三种情况 根据加法原理 fs应该等于这三种情况的和 写成递推式就是 状态压缩 引例解法 根据上面的讨论思路推广之 得到引例的解决办法 其中s的右起第i 1位为1 其实就是在枚举s的二进制表示中的1 状态压缩 引例的实现 ProgP0 read n int64f 1 220 0 f 0 1 for inti 1 i0 t t 状态压缩 对引例的思考 反思这个算法 其正确性毋庸置疑 可以和n 对比验证 但是算法的时间复杂度为O n2n 空间复杂度O 2n 是个指数级的算法 比循环计算n 差了好多 它有什么优势 还有一个

5、很 的用处 即对新手说 来看看我这个计算n 的程序 连这都看不懂就别OI了 可扩展性 状态压缩 例1 在n n n 20 的方格棋盘上放置n个车 某些格子不能放 求使它们不能互相攻击的方案总数 30s思考时间 状态压缩 例1分析 对于这个题目 如果组合数学学得不够扎实 应该很难一眼看出解法 本题确实存在数学方法 容斥原理 但因为和引例同样的理由 这里不再赘述 引例的算法是在枚举当前行 即s中1的个数 设为r 的放置位置 即枚举每个1 而对于例1 第r行可能存在无法放置的格子 怎么解决 枚举1的时候判断一下嘛 状态压缩 例1解法 事实上 我们并不需要对引例的算法进行太大的改变 只要在枚举s中的1

6、的时候判断一下是否是不允许放置的格子即可然而对于n 20 O n2n 的复杂度已经不允许我们再进行多余的判断 所以实现这个算法时应该应用一些技巧 我们用ar表示第r行不允许放置的情况 如果第r行某一位不允许放置则ar此位为0 否则为1 这可以在读入数据阶段完成 状态压缩 例1解法 然后对于需要处理的状态s 用ts s ar来代替s进行枚举 即不枚举s中的1转而枚举ts中的1 因为ts保证了不允许放置的位为0 这样就可以不用其它的判断来实现算法代码中只增加了计算a数组和r的部分 而时间复杂度没有变化 状态压缩 对例1的思考 我们直接套用引例的算法就使得看上去更难的例1得到了解决 虽然这题用容斥原

7、理更快 但容斥原理在这题上只有当棋盘为正方形 放入的棋子个数为n 且棋盘上禁止放置的格子较少时才有较简单的形式和较快的速度 如果再对例1进行推广 要在m n的棋盘上放置k个车 那么容斥原理是无能为力的 而SCR算法只要进行很少的改变就可以解决问题 这也体现出了引例中给出的算法的扩展潜力 状态压缩 例2 有一个n m的棋盘 n m 80 n m 80 要在棋盘上放k k 20 个棋子 使得任意两个棋子不相邻 求合法的方案总数5min思考 讨论 提问时间 状态压缩 例2分析 观察题目给出的规模 n m 80 这个规模要想用SC是困难的 280无论在时间还是空间上都无法承受然而我们还看到n m 80

8、稍微思考我们可以发现 9 9 81 80 即如果n m都大于等于9 将不再满足n m 80这一条件 所以 我们有n或m小于等于8 而28是可以承受的 状态压缩 例2分析 我们假设m n n是行数m是列数 则每行的状态可以用m位的二进制数表示但是本题和例1又有不同 例1每行每列都只能放置一个棋子 而本题却只限制每行每列的棋子不相邻上例中枚举当前行的放置方案的做法依然可行 我们用数组s保存一行中所有的num个放置方案 则s数组可以在预处理过程中用DFS求出 同时用ci保存第i个状态中1的个数以避免重复计算 状态压缩 例2分析 开始设计状态 本题状态的维数需要增加 原因在于并不是每一行只放一个棋子

9、也不是每一行都要求有棋子 原先的表示方法已经无法完整表达一个状态 我们用fi j k表示第i行的状态为sj且前i行总共放置k个棋子 下面用pn代替原题中的k 的方案数 沿用枚举当前行方案的做法 只要当前行的放置方案和上一行的不冲突 微观地讲 就是要两行的状态s1和s2中没有同为1的位即可 亦即s1 s2 0 状态压缩 例2解法 然而 虽然我们枚举了第i行的放置方案 但却不知道其上一行 第i 1行 的方案为了解决这个问题 我们不得不连第i 1行的状态一起枚举 则可以写出递推式 其中s1 0 即在当前行不放置棋子 j和p是需要枚举的两个状态编号 状态压缩 例2解法 本题至此基本解决 当然 实现上仍

10、有少许优化空间 例如第i行只和第i 1行有关 可以用滚动数组节省空间 这个算法时间复杂度O n pn num2 空间复杂度 滚动数组 O pn num 运用简单的组合数学知识可以求出本题中的num 144 因而对于本题的数据规模可以很快出解 状态压缩 例3 给出一个n m n 100 m 10 的棋盘 一些格子不能放置棋子 求最多能在棋盘上放置多少个棋子 使得每一行每一列的任两个棋子间至少有两个空格 题目来源 NOI2001 炮兵阵地 TOI1023 POJ118530s思考时间 状态压缩 例3分析 仍然先用DFS搜出一行可能状态s 依旧用c 保存s 中1的个数 依照例1的预处理搞定不能放置棋

11、子的格子 应该有这种意识 问题是 这个题目的状态怎么选 继续像例2那样似乎不行 原因在于棋子的攻击范围加大了 状态压缩 例3分析 但是我们照葫芦画瓢 例2的攻击范围只有一格 所以我们的状态中只需要有当前行的状态 再枚举上一行的状态即可进行递推 而本题攻击范围是两格 因此增加一维来表示上一行的状态 状态压缩 例3解法 用fi j k表示第i行状态为sj 第i 1行状态为sk时前i行至多能放置的棋子数 则状态转移方程很容易写出 显然 算法时间复杂度为O n num3 空间复杂度 滚动数组 O num2 因为棋子攻击范围为两格 可以直观地想像到本题的num不会很大 的确 可以算出本题num 60 状

12、态压缩 例3题外话 此算法还有优化空间我们分别枚举了三行的状态 还需要对这三个状态进行是否冲突的判断 这势必会重复枚举到一些冲突的状态组合在DFS出s 后 我们可以算出哪些状态对可以分别作为两行的状态 这样在DP时就不需要进行盲目的枚举 理论上效率会更高 但因为num本身很小 所以这样修改没有显著地减少运行时间 状态压缩 例3题外话 值得一提的是 本题笔者的算法虽然在理论上并不是最优 有种应用三进制的方法 但由于位运算的使用 截至07年8月17日 笔者的程序在PKUOJ上长度最短 速度第二快 但是很不幸 公元2007年8月18日 天津大学06级的某同学去掉本算法的一些关键判断 达到了更短的长度

13、 但其速度慢了3倍 状态压缩 例3题外话 这个题目是国内比赛中较早出现的状态压缩题 它告诉我们状态压缩不仅可以像前几个例题那样求方案数 而且可以求最优方案 即状态压缩思想既可以应用到递推上 SCR 又可以应用到DP上 SCDP 更说明其有广泛的应用空间 状态压缩 新的模型 看了这么多棋盘模型应用状态压缩的实例 可能会让人产生错觉 以为状态压缩只在棋盘上放棋子的题目中有用 我们暂时转移视线 来看看状态压缩在其他地方的应用 覆盖模型 状态压缩 例4 给出n m 1 n m 11 的方格棋盘 用1 2的长方形骨牌不重叠地覆盖这个棋盘 求覆盖满的方案数 经典问题TOJ1343 POJ2411 Have

14、abreak 状态压缩 例4背景 这也是个经典的组合数学问题 多米诺骨牌完美覆盖问题 或所谓二聚物问题 有很多关于这个问题的结论 甚至还有个专门的公式 谁看得懂 记得住 状态压缩 例4分析 显然 如果n m都是奇数则无解 由棋盘面积的奇偶性知 否则必然有至少一个解 很容易构造出 因此假设n m至少有一个偶数 且m n我们依然像前面的例题一样把每行的放置方案DFS出来 逐行计算 状态压缩 例4解法 用fi s表示把前i 1行覆盖满 第i行覆盖状态为s的覆盖方案数因为在第i行上放置的骨牌最多也只能影响到第i 1行 则容易得递推式 状态压缩 例4细节 首先讨论DFS的一些细节 对于当前行每一个位置

15、我们有3种放置方法 竖直覆盖 占据当前格和上一行同一列的格 水平覆盖 占据当前格和该行下一格 不放置骨牌 直接空格 如何根据这些枚举出每个 s1 s2 呢 下面介绍两种方法 状态压缩 例4DFS方法1 DFS共5个参数 分别为 p 当前列号 s1 s2 当前行和上一行的覆盖情况 b1 b2 上一列的放置对当前列两行的影响 影响为1否则为0 初始时s1 s2 b1 b2 0 p p 1 s1 s1 2 1 s2 s2 2 注意 第i行的放置方案用到第i 1行的某格时 s2中该格应为0 b1 b2 0 p p 1 s1 s1 2 1 s2 s2 2 1 b1 1 b2 0 p p 1 s1 s1

16、2 s2 s2 2 1 b1 b2 0 当p移出边界且b1 b2 0时记录此方案 状态压缩 例4DFS方法2 观察第一种方法 发现b2始终为0 知这种方法有一定的冗余 换个更自然的方法 去掉参数b1 b2 p p 1 s1 s1 2 1 s2 s2 2 p p 2 s1 s1 4 3 s2 s2 4 3 p p 1 s1 s1 2 s2 s2 2 1 当p移出边界时记录此方案 这样 我们通过改变p的移动距离成功简化了DFS过程 而且这种方法更加自然 状态压缩 例4细节 DFS过程有了 实现方法却还有值得讨论的地方前面的例题中 我们为什么总是把放置方案DFS预处理保存起来 是因为不合法的状态太多 每次都重新DFS太浪费时间 然而回到这个题目 特别是当采用第二种时 我们的DFS过程中甚至只有一个判断 递归边界 说明根本没有多少不合法的方案 也就没有必要把所有方案保存下来 对于每行都重新DFS即可 状态压缩 例4细节 这个算法时间复杂度为多少呢 因为DFS时以两行为对象 每行2m 共进行n次DFS 所以是O n 4m 这会使人误以为本算法无法通过1 n m 11的测试数据 而实际上本算法可以

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号