题目链接:https://ac.nowcoder.com/acm/contest/12548/I
分析
直线用 y = kx + b 来存,直接算交点看是否在线段上,然后根据交点和起点的距离排序即可。
注意如果这样存直线,要特判斜率不存在的情况。
还要注意计算公式,比赛中因为公式抄错就没过,后来检查了半天才发现。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long double ld;
int n,q;
const ld eps = 1e-6;
const ld INF = 1e12+5;
struct point{
ld x,y;
}p[1005],s,t;
struct line{
ld k,b;
};
vector<point> v;
point getp(line l1, line l2)
{
point res;
res.x = (l2.b - l1.b) / (l1.k - l2.k);
res.y = l1.k * res.x + l1.b;
return res;
}
ld getdis(point a,point b)
{
ld res = sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
return res;
}
bool check(point a)
{
if(fabs(getdis(a, s) + getdis(a, t) - getdis(s, t)) < eps && getdis(a, s) >= eps && getdis(a, t) >= eps) return true;
return false;
}
bool cmp(point a,point b)
{
return getdis(a, s) < getdis(b, s);
}
int main()
{
int T = 1;
//scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&q);
scanf("%Lf%Lf%Lf%Lf",&s.x,&s.y,&t.x,&t.y);
for(int i=1;i<=n;i++)
{
scanf("%Lf%Lf",&p[i].x,&p[i].y);
}
line l1;
if(fabs(s.x-t.x) < eps) l1.k = INF, l1.b = s.x;
else
{
l1.k = (t.y - s.y) / (t.x - s.x);
l1.b = t.y - l1.k * t.x;
}
for(int Q=1;Q<=q;Q++)
{
v.clear();
int x,k;
scanf("%d%d",&x,&k);
line l2;
for(int i=1;i<=n;i++)
{
point t;
if(i == x) continue;
if(fabs(p[i].x-p[x].x) < eps)
{
if(fabs(l1.k-INF) < eps) continue;
t.x = p[i].x;
t.y = l1.k * t.x + l1.b;
}
else
{
l2.k = (p[i].y - p[x].y) / (p[i].x - p[x].x);
l2.b = p[i].y - l2.k * p[i].x;
if(fabs(l1.k-INF) < eps)
{
t.x = l1.b;
t.y = l2.k * t.x + l2.b;
}
else if(fabs(l1.k-l2.k) < eps) continue;
else t = getp(l1, l2);
}
if(check(t)) v.push_back(t);
}
sort(v.begin(), v.end(), cmp);
//for(int i=0;i<v.size();i++) printf("--- %.6Lf %.6Lf\n",v[i].x,v[i].y);
if(v.size() >= k) printf("%.10Lf %.10Lf\n",v[k - 1].x,v[k - 1].y);
else printf("-1\n");
}
}
return 0;
}