两个问题的对比
来源:互联网 发布:校园网络连接 编辑:程序博客网 时间:2024/05/16 12:26
0 问题描述
问题1(CF390C): 给定若干行聊天记录 “发言人: 话”, 有些聊天记录的”发言人”是缺失的, 已知相邻对话发言人一定不同, 且每个发言人说的话里都不会包含自己的名字, 现给定可能的发言人的集合, 请填充每个对话的发言人.(来自Codeforces Round 390: http://codeforces.com/contest/754/problem/C)
问题2(LC36): 给定一个9*9的矩阵, 有些元素为空, 要求使用1-9填充空元素, 使每行, 每列, 每个3*3小矩阵(共9个)中都包含1-9这9个数字.(来自 leetcode: https://leetcode.com/problems/sudoku-solver/?tab=Description)
先说结论, 两个问题非常相似, 但是第一个问题可用动态规划求解; 由于状态转移方程极难表述, 第二个问题不能用动态规划求解
1 用一张表表述问题
对于LC36, 在初始条件下, 如果我们不对矩阵进行任何填充, 那么问题的当前状态可以用一张表进行描述, 注意, 我们可以按照从上到下,从左到右的方式遍历矩阵的每个元素, 这样我们用一维序列描述二维矩阵:
同样地, 对于CF390C, 在我们填写发言人之前, 问题的初始状态也可以用一张表描述:
一旦我们开始填写矩阵/发言人, 那么上述两张表的状态就会改变, 而且改变总是会让每行的”候选集”缩小.即, 我们列出的每行的候选集一定是最终结果的超集.
2 使用动态规划描述问题
在LC36的题意下,
在390C的题意下,
乍看上去, 这两个问题是一样的. 可是我们遗漏了一很关键的东西, 就是我们对
3 重新描述问题
对于LC36:
(i,j) 表示第i 个格子, 使用j 填- 问题跳转到
(i+1) , 引入额外的约束:”不能使用j ”, 为了表述额外约束, 我们需要修改问题的表示形式 - 于是我们返回去重新表述
(i) : 填写第i 个格子, 使用数字j , 不能使用的数字列表为k , 记为(i,j,k) - 问题再次跳转到
(i+1) : 填写第i+1 个格子, 使用数字j′ , 不能使用的数字列表为k,j , 记为(i+1,j′,[k,j′])
这样可以构造DP问题
而对于390C:
(i,j) 表示, 填写第i 行, 使用人物j - 然后跳转到
(i+1) , 问题表述为填写第i+1 行, 使用人物j′ , 不能使用人物j , 引入新的约束, 需重新表示问题 - 重新表述
i 为, 填写第i 行, 使用人物j , 不能使用人物k , 记为(i,j,k) - 再次跳转到
i+1 , 问题表述为填写i 个格子, 使用人物j′ , 不能使用人物j , 记为(i+1,j′,j)
至此, 可以构造DP问题
4 分析
这两个问题再以下方面是相同的:
- 都是一个一个的填写, 并且每个都有个候选列表
- 填写一个以后, 会影响其他人的填写
但是CF390C和LC36相比有个关键的不同点: 前者跳转时, 会不携带来自
- 对于CF390C, 问题的跳转方式是
(i,j,k)⟶(i+1,j′,j) ,(i+1) 的第三个状态与i 的第三个状态无关. - 对于LC36, 问题的跳转方式是
(i,j,[k])⟶(i+1,j′,[k,j]) ,(i+1) 的第三个状态与i 的第三个状态有关.
至此, 我们发现第一个是普通的动态规划, 第二个似乎是状态压缩动态规划.可是真是这样吗?
对于CF390C, 我们在计算
j′ : 遍历每个可能的发言人j : 直接使用问题i 的第二个状态填充
然而, 对于LC36, 我们在计算
- 元素在矩阵中受到的天然限制: 行, 列, 小3*3小矩阵中的元素.这个限制就是第1节中的表的限制.
- 元素受到
i 的限制: 父元素i 有自己的不可用数字集合, 这个集合中的数字来自于父元素i 的表, 以及父元素i 的父元素(i−1) .
这样一来, 如果你要计算
- 对于受到原始限制的数字, 我们可以通过
i 和i+1 的想对位置, 进行修正. 比如, 若i 和(i+1) 在同一行,且在同一个小矩阵中 那么我们从i 的原始限制集中去掉通过列限制提供的数字. - 对于受到
i 的先前元素限制的数字, 我们必须找到他们的生成位置, 然后根据生成位置和(i+1) 的想对位置, 来计算(i+1) 的不可用数字集合.
稍加思考就会知道, 上述两个步骤, 每一步都是几乎不可实现的.因此, LC36虽然和CF390C非常像, 但是后者可以用DP求解, 但是前者很难用DP求解.
- 两个问题的对比
- 两个数的对比
- 两个Ajax架构的对比
- 对比两个不同版本的assertEquals()
- 对比两个页面日期框的区别
- 对比两个xml文件的标签
- Blend 的两个选择工具简单对比
- java 对比两个属性文件的key
- 对比两个不同版本的assertEquals()
- php如何进行两个单词的对比
- python 对比两个list的值
- 两个卷积神经的tensorboard图表对比
- oracle两个数据库之间的内容对比
- python对比两个文件的方法
- SQL Server 对比两个数据库的索引
- svn对比乱码的问题
- js时间对比的问题
- js时间对比的问题
- Mac安装Tomcat8并使用idea写web程序
- 10006---Zookeeper
- 全排列的递归算法!
- Java的几个工厂方法解析
- 84:Sum Root to Leaf Numbers
- 两个问题的对比
- [Unity3D]-协程的介绍和使用
- oracle 存储过程的例子
- Asteroids(二分图匹配)
- 记录一下误删除了mysql表中的数据后的恢复过程
- CSDN博客发布测试
- Leetcode——91. Decode Ways
- Python生成词云的制作
- [分块] [BZOJ2724] [Violet 6] 蒲公英