在由网格点(M * x,M * y)构造的网格中给出点A(x1,y1)和点B(x2,y2)其中所有变量都是整数。我需要检查从点A到点B的线段上有多少个网格点。我知道可以通过使用扩展的欧几里得算法来完成,但我不知道如何去做。我很感谢你的帮助。使用扩展欧几里德算法来查找线段与二维网格上的点的交点数
0
A
回答
0
改写,要确定有多少数量t
满足
(1) M divides (1-t) x1 + t x2
(2) M divides (1-t) y1 + t y2
(3) 0 <= t <= 1.
让我们专注于(1)
。我们引入变量q
代表整除约束和解决的整数。t
:
exists integer q, M q = (1-t) x1 + t x2
exists integer q, M q - x1 = (x2 - x1) t.
如果x1
不等于x2
,则这给出了一个周期性的组的形式t in {a + b q | q integer}
,其中a
和b
是馏分的可能性。否则,所有t
或没有t
都是解决方案。
扩展欧几里得算法对于交叉(1)
和(2)
产生的解集有用。假设我们要计算交会
{a + b q | q integer} intersect {c + d s | s integer}.
通过表达两种不同方式的一般常见的元素,我们来到了linear Diophantine equation:
a + b q = c + d s,
其中a, b, c, d
是恒定的,q, s
是整数。让我们清楚的分母和收集方面为一体式
A q + B s = C,
其中A, B, C
是整数。当且仅当A
和B
的最大公约数g
也分为C
时,该等式才有解。使用扩展欧几里德算法计算整数系数u, v
这样
A u + B v = g.
然后,我们对每个整数k
解决
q = u (C/g) + k (B/g)
s = v (C/g) - k (A/g)
。
最后,我们必须考虑约束(3)
。这应该归结为一些算术和一个楼层的划分,但我不想详细说明(到目前为止我写的特殊情况已经需要很多时间)。
0
让我们dX = Abs(x2-x1)
和dY = Abs(y2 - y1)
然后在段格点的数量是
P = GCD(dX, dY) + 1
(包括起点和终点)
其中GCD是最大公约数(通过平时(不扩展)欧几里德算法)
(见最后属性here)
0
继David Eisenstat先生的指示我已经设法用C++编写了一个计算答案的程序。
#include <iostream>
#include <math.h>
using namespace std;
int gcd (int A, int B, int &u, int &v)
{
int Ad = 1;
int Bd = 1;
if (A < 0) { Ad = -1; A = -A; }
if (B < 0) { Bd = -1; B = -B; }
int x = 1, y = 0;
u = 0, v = 1;
while (A != 0)
{
int q = B/A;
int r = B%A;
int m = u-x*q;
int n = v-y*q;
B = A;
A = r;
u = x;
v = y;
x = m;
y = n;
}
u *= Ad;
v *= Bd;
return B;
}
int main(int argc, const char * argv[])
{
int t;
scanf("%d", &t);
for (int i = 0; i<t; i++) {
int x1, x2, y1, y2, M;
scanf("%d %d %d %d %d", &M, &x1, &y1, &x2, &y2);
if (x1 == x2) // vertical line
{
if (x1%M != 0) { // in between the horizontal lines
cout << 0 << endl;
} else
{
int r = abs((y2-y1)/M); // number of points
if (y2%M == 0 || y1%M == 0) // +1 if the line starts or ends on the point
r++;
cout << r << endl;
}
} else {
if (x2 < x1)
{
int c;
c = x1;
x1 = x2;
x2 = c;
}
int A, B, C;
C = x1*y2-y1*x2;
A = M*(y2-y1);
B = -M*(x2-x1);
int u, v;
int g = gcd(A, B, u, v);
//cout << "A: " << A << " B: " << B << " C: " << C << endl;
//cout << A << "*" << u <<"+"<< B <<"*"<<v<<"="<<g<<endl;
double a = -x1/(double)(x2-x1);
double b = M/(double)(x2-x1);
double Z = (-a-C*b/g*u)*g/(B*b);
double Y = (1-a-C*b/g*u)*g/(B*b);
cout << floor(Z) - ceil(Y) + 1 << endl;
}
}
return 0;
}
谢谢你的帮忙!请检查是否考虑到所有特殊情况。
相关问题
- 1. 序言扩展欧几里德算法
- 2. 欧几里德距离点
- 3. 欧几里德算法(JS)
- 4. 二维欧几里德矢量旋转
- 5. 使用欧几里德距离在网格上查找圆的区域?
- 6. 查找勾股数:欧几里德式
- 7. 使用欧几里德算法的最大公约数?
- 8. 欧几里德递归算法
- 9. 爪哇 - 欧几里德算法
- 10. 计算3点的欧几里德距离
- 11. 二进制GCD算法对欧几里德的算法在现代计算机
- 12. 使用欧几里德算法的GCD程序
- 13. 错误的扩展欧几里德代码
- 14. GCD - 欧几里德算法和分解算法分析
- 15. python中的欧几里德算法(减法)
- 16. 质数的欧几里德引理
- 17. 在距离另一点一定距离的二维网格上查找所有点的算法
- 18. 使用apache flink的欧几里德距离计算
- 19. 识别具有最小欧几里德距离的点
- 20. Tensorflow - 矩阵中欧几里德距离的点
- 21. RSA Python和扩展欧几里得算法来生成私钥。变量是无
- 22. 欧几里德三维数据查询的良好数据结构?
- 23. 计算二维空间中的欧几里得距离的最快方法
- 24. 查找所有线段的交点
- 25. 查找二维数组中的点
- 26. 使用集群包计算欧几里德距离时出错
- 27. 欧几里德距离数学错误
- 28. 将字符串对象表示为二维欧几里德图中的一个点
- 29. csv文件的欧几里德距离
- 30. 曼哈顿,欧几里德和切比雪夫在A *算法