问题:我们必须用来自集合S的字符填充大小为m * n的2D网格,使得得到的网格中的不同子矩阵的数量接近给定数量k。
此问题源自http://www.codechef.com/JULY14/problems/GERALD09
限制:
1·= N,M< 16个
1< = k< = m * n * m * n
| S | = 4
时间限制= 0.1秒
假设:如果两个子矩阵没有相同的尺寸,或者相应位置的至少一对字符不匹配,则两个子矩阵是不同的。
我的方法:我们可以从随机网格和循环开始,同时找到可接受的解决方案,并且在每次迭代中,我们可以根据当前状态增加/减少随机性(但我们可以卡在本地最佳状态。)
但问题是我不知道计算子网格中不同子矩阵数的有效方法。我尝试使用哈希进行计数非常快(O(n 2 m 2 )*生成/搜索子网格的哈希值的成本。 但是由于哈希值的冲突,这种方法并没有给出确切的答案,甚至在使用@Vaughn Cato的注释进行校正后,我可以进行15-25次迭代以获得最佳状态,这还不够。
最近,我了解到模拟退火可以用来解决这些问题
http://www.theprojectspot.com/tutorial-post/simulated-annealing-algorithm-for-beginners/6
我正在寻找解决这一优化问题的有效方法。
提前致谢。
答案 0 :(得分:1)
我认为他们会在某个时候发表一篇社论,但这可能是针对这一特定问题的想法:
我在本地为特定n
和m
生成所有可能数量的子矩阵。
对于n=m=3
我只有11
个81
种可能性。
对于n=3,m=4
,我只有19
个值144
。
更重要的是,当我生成值时,我在一开始就获得了所有19
个可能的选项 - 在263000
矩阵之后,我已经拥有了16M
个可能的K
矩阵。 (我按字典顺序生成)
因此,我假设,一种可能的解决方案可能是预先计算n
可以为给定m
和O(1)
提供的n-m-k
的不同值,保存种子为随机生成器或以某种其他方式使每个k
三元组需要K
个字符,对于特定的测试用例,只需检查两个相邻值 - 首先K
大于和小于给定值。 / p>
更重要的是,由于可能的nxm
值的数量不大,因此可以通过其他方式生成它们:给出K
表nx(m+1)
的所有可能值,使用适当的表格,我们只能回溯下一行中的值,并尝试获取{{1}}的{{1}}的所有不同值的所有可能矩阵。