检查 2D 网格的某个元素是否与另一个元素共享对角线、水平线或垂直线

Check if an element of a 2D grid shares a diagonal, horizontal, or vertical with another element

本文关键字:元素 对角线 共享 水平 垂直线 线或 水平线 另一个 网格 2D 是否      更新时间:2023-10-16

我正在研究n-queens问题,其中一部分是检查一个女王是否受到另一个女王的威胁,以确定一个好的董事会状态。

我有一个用 0 填充的 2D 数组,在本例中为 4x4:

0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0

我随机填充每行一个女王,在本例中由 1 表示:

0 0 1 0
1 0 0 0 
1 0 0 0
0 0 0 1

我需要检查有多少其他作品威胁到给定的碎片。如果女王与另一个女王共享水平、对角线或垂直,则会受到威胁。

但是,我不完全确定如何对角遍历数组。

int checkThreats(vector<vector<int> > board, int r, int c) {
int threats = 0;
// checks vertical and horizontal
for (int i = 0; i < board.size(); i++) {
if (board[i][c] == 1 || board[r][i] == 1) {
threats++;
}
}
// it will count itself as a threat, so less one
threats--;
return threats;
}

这是水平和垂直检查的算法。给定棋盘r, c上的位置,它检查在左、右、上、下的位置(十字+形状(存在多少个皇后。

1, 0的坐标r, c,检查的位置用x标记,如果存在威胁,则标o

x 0 1 0
o x x x
o 0 0 0
x 0 0 1

在这种情况下,threats == 1因为我们不计算原始位置。

我的问题是试图沿着对角线找到 x 形的碎片。

对角线的诀窍在于它们的长度不同(总计和单独;考虑到它们仅包含从板的边缘或角落开始的 3 个正方形,但从中间开始包含 5 个正方形(。 这种不规则性使它们更难解释。

一种策略是遍历(比如(行,考虑每行的 0(如果是主题的行(、1(如果一个不在板上(或该行对角线上的 2 个正方形。 要检查的列索引只是c0+(r-r0)c0-(r-r0)

通过一些试验和错误,我能够让算法工作。以下是在所有方向上遍历的循环:

function check(arr, row, col) {
for (i = 0; i < arr.size(); i++) {} // left/right can be iterated as normal
for (i = 0; i < arr.size(); i++) {} // top/down can be the same
// lower-right diagonal from (row, col)
for (i = row+1, j = col+1; i < arr.size() && i < arr.size(); i++, j++) {}
// upper-left diagonal from (row, col)
for (i = row-1, j = col-1; i >= 0 && j >= 0; i--, j--) {}
// lower-left diagonal from (row, col)
for (i = row-1, j = col+1; i >= 0 && j < arr.size(); i--, j++) {}
// upper-right diagonal from (row, col)
for (i = row+1, j = col-1; i < arr.size() && j >= 0; i++, j--) {}
}

当然,这仅适用于方形数组。