点上的点

Points on the same line

本文关键字:      更新时间:2023-10-16

我在做一个练习问题,这是这样的,我们得到了n对坐标(x,y),我们也得到了一个中心点,即(x0,y0))。我们被要求找到最大的点位于(x0,y0)的线上。

我的方法: - 我试图维护一个将斜率作为钥匙的哈希地图,我想获得最大的第二个值,以在同一行上获得最大点数。/p>

      mp[(yi-y0)/(xi-x0))]++; //i from 0 to n
      And iterating map and doing something line this
      if(it->second >max) //it is the iterator
      max=it->second;
      and printing max at last; 

我的方法问题 - 每当我得到(xi-x0)为0时,我会得到运行时错误。我也尝试了Atan(斜率),以便我获得学位,而不是一些未定义的值,但是仍然不起作用。

我期望的 ->如何删除此运行时错误,并且我的方法是在从点(x0,y0)的线上找到最大点的方法。

P.S - 我的母语不是英语>

我假设没有其他点具有与您的"原点"相同的坐标。

如果您的所有坐标恰好是整数,则可以保留一个 Rational 编号(即一对整数,即A Nemerator 和A emnominator )作为坡度,而不是一个真实的数字。

斜率是DeltaY / DeltaX,因此您要做的就是将这对数字分开。您只需要小心地将双人划分为他们的最大的常见除数,然后处理DeltaX为零的情况。例如:

pair<int, int> CalcSlope (int x0, int y0, int x1, int y1)
{
    int dx = abs(x1 - x0), dy = abs(y1 - y0);
    int g = GCD(dx, dy);
    return {dy / g, dx / g};
}

现在只使用CalcSlope()的返回值作为您的地图密钥。

如果您需要它,这是计算GCD的一种方法:

int GCD (int a, int b)
{
    if (0 == b) return a;
    else return gcd(b, a % b);
}

您已经接受了答案,但是我还是想分享我的方法。此方法使用以下事实:三个点abc在且仅当

时是协变量的
(a.first-c.first)*(b.second-c.second) - (a.second-c.second)*(b.first-c.first) == 0

您可以使用此属性创建一个自定义比较对象,例如

struct comparePoints {
   comparePoints(int x0 = 0, int y0 = 0) : _x0(x0), _y0(y0) {}
   bool operator()(const point& a, const point& b) {
      return (a.first-_x0)*(b.second-_y0) - (b.first-_x0)*(a.second-_y0) < 0;
   }
private:
   int _x0, _y0;
};

您可以根据

将其用作地图的比较对象
comparePoints comparator(x0, y0);
map<pair<int, int>, int, comparePoints> counter(comparator);

然后,您可以将点添加到此地图上类似于您之前所做的事情:

if (!(x == x0 && y == y0))
    counter[{x,y}]++;

通过将comparitor用作比较对象,如果!comparator(a, b) && !comparator(b,a),则在且仅当ab{x0,y0}是共线时,地图中的两个键ab被视为相等的。

这种方法的优点是,您无需分割坐标,以避免将舍入错误和零除以零的问题,或计算ATAN,这是一个昂贵的操作。

移动所有内容,以使零点处于原点:

(x i ,y i ) - =(x 0 ,y 0

然后,对于每个点(x i ,y i ),找到x i 和y i的最大常见分裂并将两个数字划分为:

k = gcd(x i ,y i
(x i ',y i `)=(y i /k,y i /k)

现在,在同一射线上的点将映射到等于点。如果(x i ,y i )与(x j ,y j )在同一光线上(x i ',y i ')=(x j ',y j ')。P>

现在找到最大的相等点集(不要忘记任何(x i ,y i )=(0,0)),您有答案。

您在这里有一个非常原始的方法!

然而,垂直线具有无限的斜率,这是这里的问题:不允许除以0。

构建的替代方案(坡度):

...
int mpvertical=0;   // a separate couner for verticals
if (xi-x0) 
   mp[(yi-y0)/(xi-x0))]++;
else if (yi-y0)    
   mpvertical++;  
// else the point (xi,yi) is the point (x0,y0):  it shall not be counted)

这很麻烦,因为您在地图中有所有内容以及此额外的计数器。但这是准确的。解决方法可能是在mp[std::numeric_limits<double>::max()]中计算此类点,但这将是一个近似值。

注释:情况是xi == x0,yi == y0对应于您的原点。这些点必须属于每条线路时都必须丢弃。

三角替代(角度):

这使用了用于将笛卡尔坐标转换为极坐标的通用atan2公式,以获取角度:

if (xi!=x0 && yi!=y0)  // the other case can be ignored 
    mp[ 2*atan((yi-y0)/((xi-x0)+sqrt(pow(xi-x0,2)+pow(yi-y0,2)))) ]++;

因此,您的MP键将是-pi和 pi之间的角度。没有更多的案例,但计算略有。

您可以隐藏这些额外的详细信息,并在功能中使用更优化的构建:

if (xi!=x0 && yi!=y0)  // the other case can be ignored 
    mp[ atan2(yi-y0, xi-x0) ]++;

您可以尝试此方法

struct vec2
{
   vec2(float a,float b):x(a),y(b){}
   float x,y;
};
bool isColinear(vec2 a, vec2 b, vec2 c)
{
   return fabs((a.y-b.y)*(a.x-c.x) - (a.y-c.y)*(a.x-b.x)) <= 0.000001 ;
}
相关文章:
  • 没有找到相关文章