给定 XY 平面中三个非共线的积分点,求出这三个点所形成的三角形内的积分点数。(如果 XY 平面上的一个点的两个坐标都是积分的,则该点被称为积分点/格点)。
例子:
输入: p = (0, 0), q = (0, 5) 和 r = (5,0)
输出: 6
解释:点 (1,1) (1,2) (1,3) (2,1) (2,2) 和 (3,1) 是三角形内的积分点。
我们可以使用Pick 定理,该定理指出以下等式对于简单多边形成立。
Pick 定理:
A = I + (B/2) -1
A ==> 多边形面积
B ==> 多边形边上的积分点数
I ==> 多边形内部的积分点数
利用上述公式,我们可以得出,
I = (2A - B + 2) / 2
我们可以使用下面的鞋带公式找到A(三角形面积)。
A = 1/2 * abs(x1(y2 - y3) + x2(y3 - y1) + x3(y1 - y2))
如何求B(三角形边上的积分点数)?
我们可以使用以下算法找到三角形任意两个顶点(V1,V2)之间的积分点数。
1. 如果 V1 和 V2 连接形成的边平行于 X 轴,则
顶点之间的
积分点数为:
abs(V1.x - V2.x) - 1
2. 类似地,如果边平行于 Y 轴,则
中间的积分点数为:
abs(V1.y - V2.y) - 1
3. 否则,我们可以
使用以下公式找到顶点之间的积分点:GCD(abs(V1.x-V2.x), abs(V1.y-V2.y)) - 1
上述公式是众所周知的事实,可以
使用简单的几何来验证。(提示:移动
边,使得其中一个顶点位于原点。)
详细解释请参阅以下链接:
javascript 两点之间的积分点数(Number of Integral Points between Two Points)
https://blog.csdn.net/hefeng_aspnet/article/details/143485181
C# 两点之间的积分点数(Number of Integral Points between Two Points)
https://blog.csdn.net/hefeng_aspnet/article/details/143485152
Python 两点之间的积分点数(Number of Integral Points between Two Points)
https://blog.csdn.net/hefeng_aspnet/article/details/143485122
Java 两点之间的积分点数(Number of Integral Points between Two Points)
https://blog.csdn.net/hefeng_aspnet/article/details/143485077
C++ 两点之间的积分点数(Number of Integral Points between Two Points)
https://blog.csdn.net/hefeng_aspnet/article/details/143484758
下面是上述算法的实现:
// C++ program to find Integral points inside a triangle
#include<bits/stdc++.h>
using namespace std;
// Class to represent an Integral point on XY plane.
class Point
{
public:
int x, y;
Point(int a=0, int b=0):x(a),y(b) {}
};
//utility function to find GCD of two numbers
// GCD of a and b
int gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a%b);
}
// Finds the no. of Integral points between
// two given points.
int getBoundaryCount(Point p,Point q)
{
// Check if line parallel to axes
if (p.x==q.x)
return abs(p.y - q.y) - 1;
if (p.y == q.y)
return abs(p.x - q.x) - 1;
return gcd(abs(p.x-q.x), abs(p.y-q.y)) - 1;
}
// Returns count of points inside the triangle
int getInternalCount(Point p, Point q, Point r)
{
// 3 extra integer points for the vertices
int BoundaryPoints = getBoundaryCount(p, q) +
getBoundaryCount(p, r) +
getBoundaryCount(q, r) + 3;
// Calculate 2*A for the triangle
int doubleArea = abs(p.x*(q.y - r.y) + q.x*(r.y - p.y) +
r.x*(p.y - q.y));
// Use Pick's theorem to calculate the no. of Interior points
return (doubleArea - BoundaryPoints + 2)/2;
}
// driver function to check the program.
int main()
{
Point p(0, 0);
Point q(5, 0);
Point r(0, 5);
cout << "Number of integral points inside given triangle is "
<< getInternalCount(p, q, r);
return 0;
}
输出:
给定三角形内的积分点数为 6
时间复杂度: O(log(min(a,b))),因为我们使用递归来查找 GCD。
辅助空间: O(log(min(a,b))),用于递归堆栈空间。