题面
题意: 给出三角形的三个顶点和一条线段的一个端点,问是否存在另外一个点和之前的端点构成一条线段,满足落在三角形边上,并且把三角形分成面积相等的两部分,起始点也需要在三角形边上。
题解: 赛后看了一下大家的blog,基本上都是用二分写的,我觉得我的写法还挺好的。首先如果起始点不在三角形边上,直接输出 -1,如果起始点在边上,那么就一定能够找到另外一个点也在三角形边上把这个三角形分为面积相等的两部分,接下来我们就需要去找到这个点,这里我用到了高中时常用的求三角形面积公式
S
=
1
2
∗
sin
θ
∗
a
∗
b
S = \frac{1}{2} * \sin\theta * a * b
S=21∗sinθ∗a∗b
以上面这张图举例,A B C是给出的三角形的三个顶点, P也是给出的,我们想要找到Q,我的方法是:首先找到P所在的直线,然后找到在这条直线上找到离P远的顶点,以这个点为公共角去寻找Q,我们可以通过下面的方程找到BQ的长度
1
2
∗
sin
B
∗
B
C
∗
B
A
=
2
∗
1
2
∗
sin
B
∗
B
P
∗
B
Q
\frac{1}{2} * \sin\ B * BC * BA = 2 * \frac{1}{2} * \sin\ B * BP * BQ
21∗sin B∗BC∗BA=2∗21∗sin B∗BP∗BQ
可以直接化简到
B
C
∗
B
A
=
2
∗
B
P
∗
B
Q
BC * BA = 2 * BP * BQ
BC∗BA=2∗BP∗BQ
因为只有BQ是未知的所以可以容易得到BQ的值,进而就可以根据BA向量的方向来确定Q的坐标了。
代码
#include<bits/stdc++.h>
using namespace std;
#define eps 1e-8
int sgn(double x){
if(fabs(x) < eps) return 0;
else return x < 0 ? -1 : 1;
}
struct Point{
double x, y;
Point(){}
Point(double x, double y):x(x),y(y){}
Point operator - (Point B){
return Point(x - B.x, y - B.y);
}
}P[5], pos[5];
struct Line{
Point p1, p2;
Line(){}
Line(Point p1, Point p2):p1(p1),p2(p2){}
}L[5];
double Dist(Point A, Point B){
return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y));
}
double Dot(Point A, Point B){
return A.x * B.x + A.y * B.y;
}
double Cross(Point A, Point B){
return A.x * B.y - A.y * B.x;
}
bool Point_on_seg(Point p, Line v){
return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 &&
sgn(Dot(p - v.p1, p - v.p2)) <= 0;
}
int t;
int main () {
scanf("%d", &t);
while(t--){
for(int i = 1; i <= 4; i++) scanf("%lf %lf", &P[i].x, &P[i].y);
L[1] = Line(P[1], P[2]);
L[2] = Line(P[2], P[3]);
L[3] = Line(P[3], P[1]);
if(Point_on_seg(P[4], L[1]) == 0 && Point_on_seg(P[4], L[2]) == 0 && Point_on_seg(P[4], L[3]) == 0){
printf("-1\n");
continue;
}
int p = 0;
for(int i = 1; i <= 3; i++){
if(Point_on_seg(P[4], L[i]) == 1){
p = i;
break;
}
}
if(p == 1) pos[1] = P[3];
else if(p == 2) pos[1] = P[1];
else pos[1] = P[2];
if(Dist(P[4], L[p].p1) > Dist(P[4], L[p].p2)){
pos[2] = L[p].p1;
pos[3] = L[p].p2;
}
else{
pos[2] = L[p].p2;
pos[3] = L[p].p1;
}
double cnt = Dist(P[4], pos[2]) / Dist(pos[2], pos[3]);
cnt = 0.5 / cnt;
double resultX = cnt * (pos[1].x - pos[2].x) + pos[2].x;
double resultY = cnt * (pos[1].y - pos[2].y) + pos[2].y;
printf("%.12f %.12f\n", resultX, resultY);
}
return 0;
}