这个问题遵循以下问题:How to sort a 2D Matrix
在上一个问题中,OP询问如何对矩阵进行排序,例如行和列的排序(M [i] [j]< = M [i + 1] [j]和M [i] [j ]< = M [i] [j + 1])。我的答案很简单:将它排序为一维数组,这样排序行和列也是如此。然后我意识到解决方案不是唯一的解决方案。
我的问题是:什么算法可以为我们提供这个问题的所有解决方案?一个明显的解决方案是回溯算法,但我确信我们可以做得更好......
同一阵列的解决方案示例:
0 0 1 2
2 2 3 3
3 5 5 6
6 6 6 6
7 7 9 9
和
0 2 3 6
0 2 5 6
1 3 5 6
2 3 6 6
7 7 9 9
并且:
0 2 3 6
0 2 5 6
1 3 5 7
2 3 6 7
6 6 9 9
和
0 2 3 6
0 2 5 6
1 3 5 7
2 3 6 9
6 6 7 9
等等...
答案 0 :(得分:1)
它将回溯最有效的生成解决方案,但是由于有很多方法,我提出了以下算法(它是伪C ++)
int mat[n][m] = {-1}; // initialize all cells with -1
int sortedArray[n * m]; // the sorted array of all numbers, increasing order
void generateAllSolutions(set<pair<int, int> > front, int depth) {
if (depth == n * m) {
printMatrix();
return;
}
for (pair<int, int> cell : front) {
mat[cell.first][cell.second] = sortedArray[depth];
newFront = front;
newFront.remove(cell);
if (cell.first < n - 1 &&
(cell.second == 0 || mat[cell.first + 1][cell.second - 1] != -1)) {
newFront.add(<cell.first + 1, cell.second>);
}
if (cell.second < m - 1 &&
(cell.first == 0 || mat[cell.first - 1][cell.second + 1] != -1))
newFront.add(<cell.first, cell.second + 1>);
}
generateAllSolutions(newFront, depth + 1);
mat[cell.first][cell.second] = -1; // backing the track
}
}
void solve() {
set<pair<int, int> > front = {<0, 0>}; // front initialized to upper left cell
generateAllSolutions(front, 0);
}
我正在做的是保留所有可能成为下一个最小数字的候选单元的“前沿”。这些基本上都是所有上层和左侧邻居都填充较小数字的单元格。
因为我建议的算法可以优化使用所有解决方案中所有单元格数量级别的操作,这对于您的任务来说应该是性能最佳的解决方案。
我想知道是否有任何聪明的解决方案,如果你的目的只是计算所有可能的解决方案(我可以立即设置一个大小为O的解决方案(min(m n ,n m ))
答案 1 :(得分:0)
一些改进回溯算法的修剪:
请注意,例如,在5 * 4排序矩阵M中,
M[0][0]
是所有元素集S
中的最小值,M[4][3]
是最大值。
M[0][1]
和M[1][0]
是S - ({M[0][0]}∪{M[4][3]})
中的两个最小值,而
M[3][3]
和M[4][2]
是其中的两个最大值。
只有2 * 2个案例。
同样地,M[1][1]
是最小值,M[3][2]
是S - {M[0][0],M[4][3],M[0][1] , M[1][0],M[3][3] , M[4][2]}
中的最大值,这是肯定的。