在最近由“AmDocs”组织的比赛中,我遇到了以下问题:(问题的基本理念)
您将获得一个固定大小为12x12的矩阵。 您将获得六个长度为6,5,5,4,3,2的线段。 矩阵有空格和填充空格。 您必须返回“是”或“否”,是否所有6个线段都可以同时适合矩阵。 这些线可以水平或垂直放置。
应该使用什么算法来解决这个问题?包装?背包?
答案 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细胞,如果你有包含那些细胞的片段,你将增加它们的长度(显然你最多可以找到两个片段)。
之后,您应该将数组放入可用的段中,因此在每次插入后,您应该分析所有剩余的段,如果它们中的任何一个与当前插入的段相交,则应减小它们的大小或分成两个。