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

时间:2018-03-10 16:29:20

标签: c++ algorithm math cartesian-coordinates

我已经给了积分(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

Image for this example for point (16, 0) (svg)

我的解决方案:

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),但这对我来说似乎并不高效。我的问题是,这个问题可以通过更好的时间复杂性解决吗?

2 个答案:

答案 0 :(得分:2)

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

排序x点

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

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

答案 1 :(得分:0)

这里的大部分步骤都显而易见:

  1. 阅读要点
  2. 读取每行的X截距(我刚发明了“x-intercept”?)
  3. 计算线条的斜率
  4. 选择最小斜率
  5. 查找具有该斜率的所有行
  6. 打印出结果
  7. 我相信所有这些都可以用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];
    }