2019ICPC南京K题 Triangle

被精度以及向量的方向逼疯了
判断点在哪一条线段上,去另外两条线上二分答案,计算分出来的三角形面积是否为总面积的一半,需要注意的是二分时l和r不同端点缩的时候也不一样,这个其他二分题解都没有提,个人感觉这是个BUG,我是把l和r更换后再二分了一次

#include <bits/stdc++.h>
#define double long double
#define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define endl '\n'
using namespace std;
const double eps=1e-10;
struct Point {
	double x,y;
};
struct Line {
	Point p1,p2;
};
int dcmp(double a,double b){
	if(fabs(a-b)<eps) return 0;
	return a>b?1:-1;
}
Point operator-(Point a,Point b){
	return {a.x-b.x,a.y-b.y};
}
bool operator==(Point a,Point b){
	return !dcmp(a.x,b.x) && !dcmp(a.y,b.y);
}
Point operator+(Point a,Point b){
	return {a.x+b.x,a.y+b.y};
}
Point operator/(Point a,double b){
	return {a.x/b,a.y/b};
}

int sign(double a){
	if(fabs(a)<eps) return 0;
	else if(a>0) return 1;
	else return -1;
}
double cross(Point a,Point b){ 
	return a.x*b.y-a.y*b.x;
}
double dot(Point a, Point b) {
	return a.x*b.x+a.y*b.y;
}
int T;
Point p[4],o1;
double S; 
bool on_segment(Point p, Line l){
	Point a=l.p1;
	Point b=l.p2; 
	return sign(cross(p - a, p - b)) == 0 && sign(dot(p - a, p - b)) <= 0;
}
double getdis(Point a,Point b){
	return hypot(a.x-b.x,a.y-b.y);
}
double getarea(double d,double h){
	return d*h/2;
}
double PLdis(Point a,Line s) {
    double A=s.p1.y-s.p2.y;
    double B=s.p2.x-s.p1.x;
    double C=(s.p1.x-s.p2.x)*s.p1.y-(s.p1.y-s.p2.y)*s.p1.x;
    return fabs(A*a.x+B*a.y+C)/sqrt((A*A+B*B));
}
double area(Point a,Point b,Point c){
	return cross(b-a,c-a);
}
Point get_line_intersection(Point p,Point v,Point q,Point w){
	Point u=p-q;
	double t=cross(w,u)/cross(v,w);
	return {p.x+t*v.x,p.y+t*v.y};
}
Point get_line_intersection(Line &a,Line &b){
	return get_line_intersection(a.p1,a.p2-a.p1,b.p1,b.p2-b.p1);
}
bool on_right(Line a,Point o) {
	return sign(area(a.p1,a.p2,o))<0;
}
bool find_area(Point o,Line L){
	Point l=L.p1,r=L.p2,mid=(l+r)/2;
	Point c;
	int cnt[4];
	memset(cnt,0,sizeof cnt);
	for(int i=0;i<3;i++) if(on_right({mid,o},p[i])) cnt[i]++;
	for(int i=0;i<3;i++) if(cnt[i]!=cnt[(i+1)%3] && cnt[i]!=cnt[(i+2)%3]) c=p[i];
	double height=PLdis(o,L);
	int times=1000;
	while(times--){
		mid=(l+r)/2;
		int flag=dcmp(S,2*getarea(getdis(c,mid),height));
		if(!flag){
			printf("%.10Lf %.10Lf\n",mid.x,mid.y);
//			cout<<fixed<<setprecision(10)<<mid.x<<" "<<mid.y<<endl;
			return 1;
		}
		else if(flag==1) r=mid;
		else l=mid;
	}
	return 0;
}
int main()
{
	scanf("%d",&T);
	while(T--){
		int flag=0;
		for(int i=0;i<3;i++) {
			scanf("%Lf%Lf",&p[i].x,&p[i].y);
		}
		scanf("%Lf%Lf",&o1.x,&o1.y);
		S=getarea(getdis(p[0],p[2]),PLdis(p[1],{p[0],p[2]}));
		for(int i=0;i<3;i++){
			if(o1==p[i]){
				Point tmp=(p[(i+1)%3]+p[(i+2)%3])/2;
				printf("%.10Lf %.10Lf\n",tmp.x,tmp.y);
				flag=1;
				break;
			}
		}
		if(flag) continue;
		for(int i=0;i<3;i++){
			if(on_segment(o1,{p[i],p[(i+1)%3]})){
				if(find_area(o1,{p[i],p[(i+2)%3]}) || find_area(o1,{p[(i+1)%3],p[(i+2)%3]})\
				|| find_area(o1,{p[(i+2)%3],p[i]}) || find_area(o1,{p[(i+2)%3],p[(i+1)%3]})){
					flag=1;
					break;
				}
			}
			if(flag) break;
		}
		if(!flag) printf("-1\n");
	}
	return 0;
}
/*
1
0 0 -50 0 66 6 -1 0
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我的Doraemon

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值