如何通过给定点(a,b)和(x,0)找到线的最大y截距?

Posted

技术标签:

【中文标题】如何通过给定点(a,b)和(x,0)找到线的最大y截距?【英文标题】:How to find largest y-intercept of lines through given points (a, b) and (x, 0)? 【发布时间】:2018-03-10 16:29:20 【问题描述】:

我给了分数(a, b),然后我给了分数(x, 0)。 现在,对于每个点 (x, 0),我用所有点 (a, b) 画线(见图)。 对于每个点(x, 0),我必须返回这些点的索引/点(a, b) 通过该点/点和点(x, 0) 的直线的哪个y 截距最大。 点 (x, 0) 的所有 x 值都大于最大值 a。数字a, b, x 是正整数。

例子:

输入

3 4 (number of (a, b) points and number of (x, 0) points - let's call them m and n)
5 3 (point A, index 0)
14 1 (point C, index 1)
10 2 (point B, index 2)
16 20 40 15 (x values of points (x, 0)) 

输出

1
0 2
0
1

我的解决方案:

int main() 
    int m, n;
    cin >> m >> n;
    vector<pair<int, int>> pointsAB(m);

    for (int i = 0; i < m; ++i) 
        cin >> pointsAB[i].first >> pointsAB[i].second;
    

    for (int j = 0; j < n; ++j) 
        int currX;
        double minSlope = 1.00;
        vector<int> indexes;
        cin >> currX;
        for (int i = 0; i < m; ++i) 
            int a = pointsAB[i].first, b = pointsAB[i].second;
            double currSlope = -((double)b) / (currX - a);
            if (currSlope < minSlope) 
                indexes.clear();
                minSlope = currSlope;
                indexes.push_back(i);
            
            else if (currSlope == minSlope) 
                indexes.push_back(i);
            
        

        cout << indexes[0];
        for (int k = 1; k < indexes.size(); ++k) 
            cout << " " << indexes[k];
        
        cout << '\n';
    

    return 0;

我对这个问题的解决方案具有时间复杂度 O(m * n) 但这对我来说似乎不是很有效。我的问题是这个问题可以用更好的时间复杂度解决吗?如何解决?

【问题讨论】:

那么您的解决方案是什么mn 是什么意思?在此处发布代码。 @meowgoesthedog 好的,我添加了我的解决方案。 m(a, b) 坐标数,n(x, 0) 坐标数 为什么是循环?最大可能值是无穷大。从您的一组点中选择斜率最大的点。 【参考方案1】:

为 a/b 点构建convex hull,只得到上半部分(真的你只需要上信封的右腿)从最右边的点开始

对 x 点进行排序

复杂度约为O(mlogm + nlogn)(取决于船体和排序方法)

从小值开始依次遍历 x-list,找到 a/b 集合的最佳点。请注意,此过程是线性的O(n+m)(我们将仅在当前点的左侧找到下一个最佳 a/b 点 - 想象旋转摇杆,一端沿 OX 轴移动,另一端位于 a/b 点集上)

【讨论】:

不错的算法。非常聪明。当然,这里的复杂程度适中。如果有很多点就值得了。看起来像是 CS 比赛的问题。 谢谢,非常好的答案。在这篇文章之前,我什至不知道存在像凸包这样的东西。【参考方案2】:

这里的大部分步骤看起来都相当明显:

    阅读要点 读取每行的 X 截距(我是不是刚刚发明了“x 截距”?) 计算线的斜率 选择最小的坡度 找到所有具有该斜率的线 打印结果

我相信所有这些都可以用 O(N) 复杂度来完成,所以总体上应该是 O(N)。

#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>

struct point 
    int x;
    int y;

    friend std::istream &operator>>(std::istream &is, point &p) 
        return is >> p.x >> p.y;
    

    friend std::ostream &operator<<(std::ostream &os, point const &p) 
        return os << "(" << p.x << ", " << p.y << ")";
    
;

struct slope_index 
    double slope;
    int index;

    bool operator<(slope_index const &other) const 
        return slope < other.slope;
    

    bool operator==(slope_index const &other) const 
        return slope == other.slope;
    
;

int main() 
    int N;
    std::cin >> N;

    // read in the points
    std::vector<point> points;
    std::copy_n(std::istream_iterator<point>(std::cin), N, std::back_inserter(points));

    // read in the X-intercept for each point:
    std::vector<int> Xs;
    std::copy_n(std::istream_iterator<int>(std::cin), N, std::back_inserter(Xs));

    // compute the slopes
    std::vector<slope_index> slopes;
    int i = 0;
    std::transform(points.begin(), points.end(),
        Xs.begin(),
        std::back_inserter(slopes),
        [&](point const &p, int currX)  return slope_index p.y / double(p.x - currX), i++ ; );

    // find the smallest slope
    auto v = *std::min_element(slopes.begin(), slopes.end());

    // find all the lines with that slope:
    auto pos = std::partition(slopes.begin(), slopes.end(), [&](auto const &s)  return v == s; );

    // print out the results:
    for (auto s = slopes.begin(); s != pos; ++s)
        std::cout << points[s->index];

【讨论】:

以上是关于如何通过给定点(a,b)和(x,0)找到线的最大y截距?的主要内容,如果未能解决你的问题,请参考以下文章

数百万个 3D 点:如何找到最接近给定点的 10 个?

matlab中如何计算一条线的长度

如何在Excel中找到4个数据点的x和y坐标截距?

给定 10 个函数 y=a+bx 和 1000 个 (x,y) 数据点四舍五入为整数,如何推导出 10 个最佳 (a,b) 元组?

机器学习-有监督-SVM

在给定平面法线的平面上找到一个点和沿该法线的一个点