2021 ICPC昆明 I.Mr. Main and Windmills

题目链接

题意:

一个点走过一条线段,在线段的同一侧有许多点,随着点的移动,从线段上的这个点看这些点的视角会发生变化。目光可以看成一条直线,顺时针扫过整个平面,然后对于每个点进入视野的时间就会有先后顺序。问 m m m次对于最初的第 h h h个点第 k k k次交换位置的时候,此时线段上的点的位置坐标。

题解:

对于一个给定的点,与其他点会形成多条直线,我们可以求出这些直线与给定线段的交点。根据这些交点与线段起点的距离排序,交换 k k k次时所观察的坐标就是排序后第 k k k个交点的坐标。

实现细节见代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int MAXN = 1e6 + 10;

struct Point {
	double x, y;
	Point(){}
	Point(double _x, double _y) {
		x = _x;
		y = _y;
	}
	Point operator - (const Point &b) const {
		return Point(x - b.x, y - b.y);
	}
	double operator ^ (const Point &b) const {
		return x * b.y - y * b.x;
	}
}s, e, p[MAXN];
struct Line {
	Point s, e;
	Line(){}
	Line(Point _s, Point _e) {
		s = _s;
		e = _e;
	}
}line[MAXN];
Point get_line_intersection(Point p, Point v, Point q, Point w) {
	auto u = p - q;
	double t = (w ^ u) / (v ^ w);
	return Point{p.x + v.x * t, p.y + v.y * t};
}
Point get_line_intersection(Line a, Line b) {
	return get_line_intersection(a.s, a.e - a.s, b.s, b.e - b.s);
}
bool cmp(Point a, Point b) {
	double len1 = hypot(a.x - s.x, a.y - s.y);
	double len2 = hypot(b.x - s.x, b.y - s.y);
	return len1 < len2;
}
Point all[MAXN];
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int n, m;
	cin >> n >> m;
	cin >> s.x >> s.y >> e.x >> e.y;
	int cnt = 0;
	Line o{s, e};
	for (int i = 1; i <= n; i++) {
		cin >> p[i].x >> p[i].y;
	}
	while (m--) {
		int h, k, num = 0;
		cnt = 1;
		cin >> h >> k;
		for (int i = 1; i <= n; i++) {
			if (i != h) {
				Line now{p[h], p[i]};
				Point cur = get_line_intersection(o, now);
				if (cur.x < min(s.x, e.x) || cur.x > max(s.x, e.x) || cur.y < min(s.y, e.y) || cur.y > max(s.y, e.y)) continue; // 如果交点不在线段上不考虑
				all[num++] = cur;
			}
		}
		if (k > num) {
			cout << -1 << endl;
			continue;
		}
		sort(all, all + num, cmp);
		cout << fixed << setprecision(10) << all[k - 1].x << " " << fixed << setprecision(10) << all[k - 1].y << endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值