我需要找到在网格中两点之间获得的最小步数。如果您位于中心,并且只能在8个方向上移动到您周围的整数点,那么到达目的地点所需的步骤最少?
我有一个解决方案,但它非常难看,我老实说有点惭愧:
/**
* @details Each point in the graph is a linear combination of these vectors:
*
* [x] = a[0] + b[1] + c[1] + d[ 1]
* [y] [1] [1] [0] [-1]
*
* EQ1: c + b + d == x
* EQ2: a + b - d == y
*
* Any path can be simplified to involve at most two of these variables, so we
* can solve the linear equations above with the knowledge that at least two of
* a, b, c, and d are 0. The sum of the absolute value of the coefficients is
* the number of steps taken in the grid.
*/
unsigned min_distance(point_t start, point_t goal)
{
int a, b, c, d;
int swap, steps;
int x, y;
x = goal.x - start.x;
y = goal.y - start.y;
/* Possible simple shortcuts */
if (x == 0 || y == 0) {
steps = abs(x) + abs(y);
} else if (abs(x) == abs(y)) {
steps = abs(y);
} else {
b = x, a = y - b;
steps = abs(a) + abs(b);
c = x, a = y;
swap = abs(a) + abs(c);
if (steps > swap)
steps = swap;
d = x, a = y + d;
swap = abs(a) + abs(d);
if (steps > swap)
steps = swap;
b = y, c = x - b;
swap = abs(b) + abs(c);
if (steps > swap)
steps = swap;
b = (x + y) / 2, d = b - y;
swap = abs(b) + abs(d);
if ((x + y) % 2 == 0 && steps > swap)
steps = swap;
d = -y, c = x - d;
swap = abs(c) + abs(d);
if (steps > swap)
steps = swap;
}
return steps;
}
顶部的注释解释了实际算法:将每个有效步骤表示为矩阵中的列向量,然后找到所得线性方程组的最小解。
在这种情况下,我看到最好的答案最多使用两个变量,并通过将变量的不同组合设置为0来解决方程六次。这太具体了!我希望能够更改有关哪些步骤有效且仍能找到最小距离的规则。
编辑:我意识到这是我正在尝试做的一个非常糟糕的简单示例,因为在这种情况下简化问题是多么容易。目标是计算给定任意步进规则的步数。如果它允许的步骤看起来像this那么我将从一个不同的矩阵([0 2 3 4 x; 1 2 0 -4 y])开始,找到不同方程组的最小解( 2b + 3c + 4d = x,a + 2b - 4d = y)。我实际上是在尝试编写一个可以处理任何向量集的过程来找到最小步数。......有任何建议或批评吗?