2019ICPC南京站K-Triangle (计算几何+相似求解)

**在这里插入图片描述**
题意:给定你一个三角形的三个顶点,三角形一定是合法的,然后在给定你一个平面内的点,这个点可能不落在三角形的某一条边上,如果是这种情况那么就不合法输出-1,否则输出三角形边上的一个点的坐标使之与给定点连接形成的线段能够平分三角形的面积。

思路:首先合不合法的情况,我们可以利用叉积和点积判断,点要在三角形的边上,那么,叉积一定要等于0并且点积要是个负数,否则输出-1即可。

既然要平分面积,在这里插入图片描述
假设给定的点p在点1,2那条边上,此时我们求出p到点1和点2的距离,如果d1 > d2(即图中p),否则为p’。这里以p为例,求出点p和点2分别到边13的距离d和h,边13的中点为mid,此时如果点x和点p的连线能够平分面积,就应该有 dis(mid,1) * h = dis(x,1) * d,可以解得 dis(x,1) = dis(mid,1) * (h/d)。然后就可以利用向量加减求出x的坐标了。
点p’类似无非就是往边23作高就可,给出的点在其他两条边的答案类似。
分类讨论即可。
然后flag代表的对应的边,点在三角形顶点处直接特判即可。

代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const double eps = 1e-10;
//直接模拟
int sign(double x)//判断符号可用
{
	if(fabs(x) <= eps) return 0;
	if(x > 0) return 1;
	else return -1;
}

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);
	}
	Point operator - (const Point &b)const{
		return Point(x-b.x,y-b.y);
	}
	Point operator * (const double &k)const{//乘常数
		return Point(x*k,y*k);
	}
	Point operator / (const double &k)const{
		return Point(x/k,y/k);
	}
	double len(){ return x * x + y * y; }
};

typedef Point Vector;

double cross(Vector a,Vector b){
	return a.x * b.y - a.y * b.x;
}

double dot(Vector a,Vector b){
	return a.x * b.x + a.y * b.y;
}
double dis(Point a,Point b){
	return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}

int main(){
	Point p[4],pp,ans;
	int T;scanf("%d",&T);
	while(T--){
		for(int i = 1;i <= 3;i ++) scanf("%lf%lf",&p[i].x,&p[i].y);
			scanf("%lf%lf",&pp.x,&pp.y);
		if(pp.x == p[1].x && pp.y == p[1].y){
			Point mid = (p[2] + p[3]) / 2.0;
			printf("%.10f %.10f\n",mid.x,mid.y);
			continue;
		}
		if(pp.x == p[2].x && pp.y == p[2].y){
			Point mid = (p[1] + p[3]) / 2.0;
			printf("%.10f %.10f\n",mid.x,mid.y);
			continue;
		}
		if(pp.x == p[3].x && pp.y == p[3].y){
			Point mid = (p[1] + p[2]) / 2.0;
			printf("%.10f %.10f\n",mid.x,mid.y);
			continue;
		}
		int flag = 0;
		Vector v1 = pp - p[1],v2 = pp - p[2],v3 = pp - p[3];
		if(sign(dot(v1,v2)) == -1 && sign(cross(v1,v2)) == 0) flag = 1;		
		else if(sign(dot(v1,v3)) == -1 && sign(cross(v1,v3)) == 0) flag = 2;
		else if(sign(dot(v2,v3)) == -1 && sign(cross(v2,v3)) == 0) flag = 3;
		if(!flag) { printf("-1\n");continue; }
		// cout<<"***"<<flag<<endl;
		if(flag == 1){
			double d1 = dis(pp,p[1]),d2 = dis(pp,p[2]);
			if(fabs(d1 - d2) <= eps) ans = p[3];
			else {
				if(d1 > d2){
					double rate;
					Vector tv1 = pp - p[1],tv2 = p[3] - p[1],tv3 = p[2] - p[1];
					double dd = fabs(cross(tv1,tv2)) / tv2.len();
					double hh = fabs(cross(tv3,tv2)) / tv2.len();
					rate = hh / dd;
					// cout<<"***"<<rate<<endl;
					// cout<<hh<<' '<<dd<<endl;
					ans = p[1] + (p[3]-p[1]) * 0.5 * rate;
				}
				else{
					double rate;
					Vector tv1 = pp - p[2],tv2 = p[3] - p[2],tv3 = p[1] - p[2];
					double dd = fabs(cross(tv1,tv2)) / tv2.len();
					double hh = fabs(cross(tv3,tv2)) / tv2.len();
					rate = hh / dd;
					// cout<<"***"<<rate<<endl;
					// cout<<hh<<' '<<dd<<endl;
					ans = p[2] + (p[3]-p[2]) * 0.5 * rate;
				}
			}
		}
		else if(flag == 2){
			double d1 = dis(pp,p[1]),d2 = dis(pp,p[3]);
			if(fabs(d1 - d2) <= eps) ans = p[2];
			else {
				if(d1 > d2){
					double rate;
					Vector tv1 = pp - p[1],tv2 = p[2] - p[1],tv3 = p[3] - p[1];
					double dd = fabs(cross(tv1,tv2)) / tv2.len();
					double hh = fabs(cross(tv3,tv2)) / tv2.len();
					rate = hh / dd;
					// cout<<hh<<' '<<dd<<endl;
					// cout<<"***"<<rate<<endl;
					ans = p[1] + (p[2]-p[1]) * 0.5 * rate;
				}
				else{
					double rate;
					Vector tv1 = pp - p[3],tv2 = p[2] - p[3],tv3 = p[1] - p[3];
					double dd = fabs(cross(tv1,tv2)) / tv2.len();
					double hh = fabs(cross(tv3,tv2)) / tv2.len();
					rate = hh / dd;
					// cout<<hh<<' '<<dd<<endl;
					// cout<<"***"<<rate<<endl;
					ans = p[3] + (p[2]-p[3]) * 0.5 * rate;
				}
			}
		}
		else if(flag == 3){
			double d1 = dis(pp,p[2]),d2 = dis(pp,p[3]);
			if(fabs(d1 - d2) <= eps) ans = p[1];
			else {
				if(d1 > d2){
					double rate;
					Vector tv1 = pp - p[2],tv2 = p[1] - p[2],tv3 = p[3] - p[2];
					double dd = fabs(cross(tv1,tv2)) / tv2.len();
					double hh = fabs(cross(tv3,tv2)) / tv2.len();
					rate = hh / dd;
					ans = p[2] + (p[1]-p[2]) * 0.5 * rate;
				}
				else{
					double rate;
					Vector tv1 = pp - p[3],tv2 = p[1] - p[3],tv3 = p[2] - p[3];
					double dd = fabs(cross(tv1,tv2)) / tv2.len();
					double hh = fabs(cross(tv3,tv2)) / tv2.len();
					rate = hh / dd;
					ans = p[3] + (p[1]-p[3]) * 0.5 * rate;
				}
			}
		}
		printf("%.10f %.10f\n", ans.x, ans.y);
	}
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值