将线拟合成网格矩阵[竞争,而不是HW]

时间:2012-08-23 20:12:43

标签: algorithm matrix 2d dynamic-programming knapsack-problem

在最近由“AmDocs”组织的比赛中,我遇到了以下问题:(问题的基本理念)

您将获得一个固定大小为12x12的矩阵。 您将获得六个长度为6,5,5,4,3,2的线段。 矩阵有空格和填充空格。 您必须返回“是”或“否”,是否所有6个线段都可以同时适合矩阵。 这些线可以水平或垂直放置。

应该使用什么算法来解决这个问题?包装?背包?

3 个答案:

答案 0 :(得分:4)

我会将问题映射到SAT并使用SAT求解器。有一个非常自然的映射。定义变量:

x_s_i_j_d = segment s starts at coordinates (i,j) and goes in direction d

(d是“正确”或“向下”)

首先,迭代所有段和起始位置,并查看给定起始矩阵哪些是可行的。 例如,M:

000000000000
111111111111
...

如果段1的长度为2,则为L_seg1_0_0_down = false,因为它会到达填充空间。

然后,编写禁止两个交叉段的条款。如果段1和段2都是长度2,那么我们添加子句:

(!L_seg1_0_0_right || !L_seg2_1_0_right)

因为如果段1使用坐标(0,0)和(1,0),则段2也不能使用(1,0)。

最后,添加每个段必须至少使用一次的条件:

(L_seg1_0_0_right || L_seg1_0_1_right || ...)

对于seg1可以去的所有位置。然后把你最​​喜欢的SAT求解器扔到它上面。

答案 1 :(得分:0)

我会使用贪婪的填充算法,如下所示:

for largest_line to smallest_line do
  for first_empty_square_in_matrix to last_empty_square_in_matrix do
    if line_fits_horizontal then
      place_line
      break
    else if_line_fits_vertical then
      place_line
      break
if all_lines_placed then
  write('Yes')
else
  write('No')

为了优化上述内容,您可能会注意到,如果长度为n的水平线无法适合位置(i,j),那么您将无需在(i + 1,j)中的任何一个上水平拟合它中,(i + 2,j)的...(I + N,j)的

答案 2 :(得分:0)

只是一个想法:
迭代所有2D阵列点并创建可用段的集合。在每一步,你将分析i-1和j-1细胞,如果你有包含那些细胞的片段,你将增加它们的长度(显然你最多可以找到两个片段)。
之后,您应该将数组放入可用的段中,因此在每次插入后,您应该分析所有剩余的段,如果它们中的任何一个与当前插入的段相交,则应减小它们的大小或分成两个。