我正在研究一些我觉得NP难的问题。所以,我不是在寻找最佳解决方案,但我正在寻找更好的启发式方法。给出整数输入矩阵(以下示例中的矩阵A)作为输入,我必须生成一个整数输出矩阵(以下示例中的矩阵B),其行数小于输入矩阵,并且应遵循以下两个条件:
1)输出矩阵的每一列应包含与输入矩阵中出现的顺序相同的整数。 (在下面的例子中,矩阵A和矩阵B的第一列具有相同的整数1,3。)
2)相同的整数不能出现在同一行中(在下面的例子中,矩阵B的第一行包含整数1,3和2,它们彼此不同。)
请注意,输入矩阵始终遵循第二个条件。
解决这个问题的贪婪算法是什么样的?
示例:
在此示例中,输出矩阵“Matrix B”包含输入矩阵“Matrix A”中出现的所有整数,但输出矩阵有5行,输入矩阵有6行。因此,输出'Matrix B '是输入'矩阵A'的有效解决方案。
答案 0 :(得分:3)
我会一次生成一行输出。当计算出要放入行的内容时,我会考虑每个输入列的下一个数字,从输入列开始,该数字尚未放置,并考虑按数字递减顺序排列的列。当一列可以在轮到它时将数字放在当前输出行中,它应该这样做。
您可以将其扩展到分支和绑定解决方案,以找到确切的最佳答案。在每个阶段递归尝试所有可能的行,除非您可以看到当前行无法改进到目前为止的最佳答案。你知道,如果你有一个列有k个条目的列,那么在最好的情况下你至少需要k行。
在实践中,我希望这样做太昂贵而不实用,所以你需要忽略一些你不能排除的行,因此无法保证找到最佳答案。您可以尝试使用启发式搜索,例如Limited Discrepancy search。
另一个非精确加速是将乘以部分解的最佳可能答案所需的行数估计乘以某个因子F> 1。这将允许您在分支和绑定之前排除某些解决方案。你找到的答案不会超过最佳答案的F倍,因为你只丢弃了不能提高当前答案的可能性超过F的因素。
答案 1 :(得分:0)
这个问题的贪婪解决方案是将数字逐列(自上而下)逐列放置。
伪代码:
For each column c in A:
r = 0 // row index of next element in A
nextRow = 0 // row index of next element to be placed in B
while r < A.NumRows()
while r < A.NumRows() && A[r, c] is null:
r++ // increment row to check in A
if r < A.NumRows() // we found a non-null entry in A
while nextRow < A.NumRows() && ~CheckConstraints(A[r,c], B[nextRow, c]):
nextRow++ // increment output row in B
if 'nextRow' >= A.NumRows()
return unsolvable // couldn't find valid position in B
B[nextRow, c] = v // successfully found position in B
++nextRow // increment output row in B
如果没有冲突你就会结束&#34;打包&#34; B尽可能紧密。否则,您贪婪地在B
中搜索下一个不冲突的行位置。如果找不到,则问题无法解决。
辅助函数CheckConstraints
向后检查B
中相同行值的列,以确保相同的值尚未排成一行。
如果问题陈述被放宽,使得B中的输出行数<= A中的行数,那么如果我们无法将B打包得更紧,那么我们可以返回A作为解决方案。