两个问题的对比
2017-03-10 23:52
169 查看
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, 在初始条件下, 如果我们不对矩阵进行任何填充, 那么问题的当前状态可以用一张表进行描述, 注意, 我们可以按照从上到下,从左到右的方式遍历矩阵的每个元素, 这样我们用一维序列描述二维矩阵:元素编号 | 可能的填充数字 |
---|---|
1 | a11,a12,... |
2 | a21,... |
… | … |
81 | a81,1,a81,2,... |
聊天记录 | 可能的发言人 |
---|---|
第1条记录 | b11,b12,... |
第2条记录 | b21,... |
… | … |
第n条记录 | bn1,... |
2 使用动态规划描述问题
在LC36的题意下, (i,j)表示填第i个元素, 使用数字j, 然后问题跳转到(i+1,j′)在390C的题意下, (i,j)表示填第i个对话, 使用第j个人, 然后问题跳转到(i+1,j′)
乍看上去, 这两个问题是一样的. 可是我们遗漏了一很关键的东西, 就是我们对(i+1,j′)的表述是不完整的.因为我们无论何时, 只要我们填写了i, 那么在我们填写i+1时就会受到我们刚才的填写行为的约束. 即问题i的决策会对问题i+1产生影响, 但是我们并没有表述出这种影响.
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问题[y,x,i,M] 表示在不能使用数字的屏蔽码为M的情况下用i台填写格子(y,x),并且不会破坏矩阵性质的可能性(可能/不可能), 复杂度是: 9*9*9*512 < 1000 * 600 = 600, 000, 貌似可解
而对于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问题[i,j,k], 表示从第i个人开始填写, 使用j号人物, 不能使用k号人物, 最终可以成功填写的可能性(可能/不可能).
4 分析
这两个问题再以下方面是相同的:都是一个一个的填写, 并且每个都有个候选列表
填写一个以后, 会影响其他人的填写
但是CF390C和LC36相比有个关键的不同点: 前者跳转时, 会不携带来自(i−1)的约束, 而后者会携带来自(i−1)的约束:
对于CF390C, 问题的跳转方式是(i,j,k)⟶(i+1,j′,j), (i+1)的第三个状态与i的第三个状态无关.
对于LC36, 问题的跳转方式是(i,j,[k])⟶(i+1,j′,[k,j]), (i+1)的第三个状态与i的第三个状态有关.
至此, 我们发现第一个是普通的动态规划, 第二个似乎是状态压缩动态规划.可是真是这样吗?
对于CF390C, 我们在计算(i,j,k)时可以很方便地算出(i+1)的两个状态参数:
j′: 遍历每个可能的发言人
j: 直接使用问题i的第二个状态填充
然而, 对于LC36, 我们在计算(i,j,k)时却很难算出(i+1)的第三个参数!我们来看第三个参数的意义:不能使用的数字集合.这个参数的计算过程是这样的: 一方面, 如果i号元素是定值, 那么第三个参数k也是定值, 直接计算;另一方面, 如果i号元素为空, 那么第三个状态k的计算要考虑如下因素:
元素在矩阵中受到的天然限制: 行, 列, 小3*3小矩阵中的元素.这个限制就是第1节中的表的限制.
元素受到i的限制: 父元素i有自己的不可用数字集合, 这个集合中的数字来自于父元素i的表, 以及父元素i的父元素(i−1).
这样一来, 如果你要计算(i+1)的第三个参数, 必须清楚地知道, 父元素不可用数字集中每个数字是如何生成的:
对于受到原始限制的数字, 我们可以通过i和i+1的想对位置, 进行修正. 比如, 若i和(i+1)在同一行,且在同一个小矩阵中 那么我们从i的原始限制集中去掉通过列限制提供的数字.
对于受到i的先前元素限制的数字, 我们必须找到他们的生成位置, 然后根据生成位置和(i+1)的想对位置, 来计算(i+1)的不可用数字集合.
稍加思考就会知道, 上述两个步骤, 每一步都是几乎不可实现的.因此, LC36虽然和CF390C非常像, 但是后者可以用DP求解, 但是前者很难用DP求解.
相关文章推荐
- Unix网络的两个安全问题
- (旧文重贴)前段时间关于SmartClient部署的两个问题,都搞定了。
- 今天搞定两个问题
- [导入]WindowsXp的两个问题:
- MS员工需要跟老板核实的两个问题
- 求助 谢谢 两个问题
- 关于c#中两个DataGrid绑定到主表和子表的数据同步问题
- 在VS.NET 2003中建立项目时遇到的两个问题及解决方法 (转贴)
- 摘之网上,两个很基本的问题的解答。
- Q: "为什么如果我们把这两个组件安装在同一个COM+组件包中问题就不会出现"(zz)
- Google Desktop Search两个问题?
- [全程建模]与一个朋友讨论的关于书上的两个问题
- 在VS.NET 2003中建立项目时遇到的两个问题及解决方法
- 关于C#中实现两个应用程序消息通讯的问题
- Fedora Core 2,两个问题及及解决办法
- 两个需要解决的问题
- 关于RICHEDIT的两个问题
- hibernate中如何实现两个无关系表的左联的问题
- [原创]两个listbox之间操作数据交换的问题!
- 上传,注意的两个问题