如何找到通过给定点 (a, b) 和 (x, 0) 的最大 y-intercept 线?
How to find largest y-intercept of lines through given points (a, b) and (x, 0)?
我给了积分(a, b)
然后我给了积分(x, 0)
。
现在对于每个点 (x, 0)
我用所有点 (a, b)
画线(见图)。
对于每个点 (x, 0)
我必须 return 索引 point/points (a, b)
通过此 point/points 和点 (x, 0)
的线 y-intercept 最大。
点 (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) 但这对我来说似乎不是很有效。我的问题是这个问题可以用更好的时间复杂度来解决吗?如何解决?
建造convex hull获得a/b分,只得到上半部分(真的你只需要上包络的右腿)从最右边开始按顺序点
排序x-points
复杂度约为 O(mlogm + nlogn
)(取决于外壳和排序方法)
从小值开始按顺序遍历 x-list,找到 a/b 集的最佳点。请注意,此过程是线性的 O(n+m)
(我们会在当前点的左侧找到下一个最佳 a/b 点 - 想象旋转杆,一端沿 OX 轴移动,另一端停留在 a/b点集)
这里的大部分步骤似乎都很明显:
- 阅读要点
- 读入每一行的 X-intercept(我刚刚发明了 "x-intercept" 吗?)
- 计算直线的斜率
- select最小坡度
- 找到所有具有该斜率的直线
- 打印出结果
我相信所有这些都可以用 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)
。
现在对于每个点 (x, 0)
我用所有点 (a, b)
画线(见图)。
对于每个点 (x, 0)
我必须 return 索引 point/points (a, b)
通过此 point/points 和点 (x, 0)
的线 y-intercept 最大。
点 (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) 但这对我来说似乎不是很有效。我的问题是这个问题可以用更好的时间复杂度来解决吗?如何解决?
建造convex hull获得a/b分,只得到上半部分(真的你只需要上包络的右腿)从最右边开始按顺序点
排序x-points
复杂度约为 O(mlogm + nlogn
)(取决于外壳和排序方法)
从小值开始按顺序遍历 x-list,找到 a/b 集的最佳点。请注意,此过程是线性的 O(n+m)
(我们会在当前点的左侧找到下一个最佳 a/b 点 - 想象旋转杆,一端沿 OX 轴移动,另一端停留在 a/b点集)
这里的大部分步骤似乎都很明显:
- 阅读要点
- 读入每一行的 X-intercept(我刚刚发明了 "x-intercept" 吗?)
- 计算直线的斜率
- select最小坡度
- 找到所有具有该斜率的直线
- 打印出结果
我相信所有这些都可以用 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];
}