c++ 计算三角形内的积分点(Count Integral points inside a Triangle)

        给定 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))),用于递归堆栈空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

csdn_aspnet

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值