队友开始都在开L题,感觉没有进展我就看了看计算几何,发现意外的简单,后来陆陆续续队友有L题想法就上,WA了几发L的同时我写出了I题,结果发现段错误,原来是题目读错了,稍加修改一发过(英语的重要性)。
据说很多人卡精度,不知道为什么,我把我的定义改成double也还是能过。可能我用的是自己手推的公示,用的是小学二年级就学过的y=kx+b 斜率方程式求。据说别人模板精度改成1e-1就过了。
题面:
题意大概是一个火车从一点到另一个点。有n个风车,会随着位置的移动在火车视角看,位置会向左或者向右偏移,求的是h风车相对位置变化的第k次的点。
都说到这个地步了 可以说是非常简单了(自认为,出题人也说比较简单,看看吓跑多少个看到计算几何就跑的。)无非就是求开始的线段方程,然后第hi点和其他所有点的方程与列车行进路线轨迹方程的交点,sort一下,复杂度是nmlogn,当时还有点担心会T因为有点极限,结果直接过了。
代码:
#include "bits/stdc++.h"
#define LD long double//这里使用double也能过,看来不是卡long double的精度
using namespace std;
const int MAXN = 1005;
const double INF = 1e9 + 7;
struct point {
LD x, y;
}A[MAXN], stk[MAXN];
LD slope (point a, point b) {
if (b.x == a.x) return INF;
return (b.y - a.y) / (b.x - a.x);
}
struct line {
LD k, b;
point fromP, endP;
line(){}
line(point a, point c) {
k = slope(a, c);
b = c.y - c.x * k;
if (k == INF) b = c.x;
fromP = a, endP = c;
}
void out () {
printf("k:%LF, b:%LF\n", k, b);
}
};
point findPoint(line a, line b) {//找到两个线的交点
if (a.k == b.k) return point{INF, INF};
LD xpos, ypos;
if (a.k == INF) {
xpos = a.fromP.x;
}else if (b.k == INF) {
xpos = b.fromP.x;
}else {
xpos = (b.b - a.b) / (a.k - b.k);
}
if (a.k == 0) {
ypos = a.fromP.y;
}else if (b.k == 0) {
ypos = b.fromP.y;
}else {
ypos = xpos * a.k + a.b;
}
return point{xpos, ypos};
}
int getAllPoint(int n, int p, line city) {//求得该点和所有点连线与轨道线的交点
int cnt = 0;
point s = city.fromP, t = city.endP;
for (int i = 1; i <= n; ++i) {
if (i == p)continue;
line now = line(A[i], A[p]);
if (city.k == now.k) {//平行必定没交点
continue;
}
point get = findPoint(city, now);
if (get.x < min(s.x, t.x) || get.x > max(s.x, t.x) || get.y > max(s.y, t.y) || get.y < min(s.y, t.y)) {
continue;
}
stk[++cnt] = get;
}
return cnt;
}
int main(void) {
int n, m;
cin >> n >> m;
point s, t;
cin >> s.x >> s.y >> t.x >> t.y;
line city = line(s, t);
//city.out();
for (int i = 1; i <= n; ++i) {
cin >> A[i].x >> A[i].y;
}
for (int i = 0; i < m; ++i) {
int h, k;
cin >> h >> k;
int len = getAllPoint(n, h, city);
if (city.k == 0) {//将所有点排序,如果k是0,即平行于x轴就以x坐标排序,不然用y坐标排序
sort(stk + 1, stk + 1 + len,[](point a, point b){return a.x < b.x;});
}else {
sort(stk + 1, stk + 1 + len, [](point a,point b){return a.y < b.y;});
}
if (len < k) {
cout << -1 << endl;
}else {
if (s.y > t.y) reverse(stk + 1, stk + 1 + len);
if (city.k == 0 && s.x > t.x) reverse(stk + 1, stk + 1 + len);
printf("%.10LF %.10LF\n", stk[k].x, stk[k].y);
}
}
return 0;
}