hiho225 Inside Triangle

版权声明:转载我的原创博客情注明出处 https://blog.csdn.net/qq_31964727/article/details/83386878

目录

题目1 : Inside Triangle

题意分析:

1.题是什么?

2.思路

   (1).面积法

           (2).点代一般式法

   (3).矢量法

3.ac代码

    (1).面积法

    (2)点代一般式法

    (3)矢量法


题目1 : Inside Triangle

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

Determine if a point is inside a 2D triangle.

输入

The first line contains an integer T denoting the number of test case. (1 <= T <= 10)

The following T lines each contain 8 integers, Px, Py, Ax, Ay, Bx, By, Cx, Cy. P denotes the point. ABC denotes the triangle. The coordinates are within [-1000000, 1000000].

输出

For each test case output YES or NO denoting if the point is inside the triangle. Note that the point is considered inside the triangle if the point is just on some side of the triangle.

样例输入

2  
0 1 -1 0 1 0 0 2  
0 0 0 1 1 0 1 1

样例输出

YES  
NO

题意分析:

1.题是什么?

    题倒是清晰明了,给你四个点p,a,b,c,判断p是否在三角形abc内

2.思路

    我有两种处理大方向:

     第一种面积比较思路,计算S_{pab}+S_{pbc}+S_{pac}与S_{abc}比较,与S_{abc}比较,相等则在三角形内,否则不在,至于为什么会这样子画个草图看看就明白了.

     第二种基于p点位置做判断思路,核心思维为判断p和a是否在直线bc的同侧,p和b是否在直线ac的同侧,p和c是否在直线ab的同侧,三个都满足则p在abc中.

   (1).面积法

    第一种面积法,已知三点(x1,y1),(x2,y2),(x3,y3)时S=fabs(0.5*(x_{1}*(y_{2}-y_{3})+x_{2}*(y_{3}-y_{1})+x_{3}*(y_{1}-y_{2})))

    以此公式直接计算S_{pab}+S_{pbc}+S_{pac}与S_{abc}比较S_{abc}比较即可,实际代码中S计算被我去掉了0.5,避免精度问题,不影响最终结果.

下面由第二种思路衍生两种方法:

    (2).点代一般式法

    首先根据ab点求出直线ab一般式方程,然后将p与c分别代入ab一般式方程结果相乘为负则p与c不在ab的同侧,p与a,p与b同样处理,三个皆同侧,即p在abc内.

    tips:这里我的算法中直线一般式可能不是最简形式,故而中间数据大小可能达到1000000^{4},会爆掉long long,故而我对于getpsbaseonline()函数的返回值做了缩小,仅仅保留我需要的正负特征,这一步必不可少.

    (3).矢量法

    首先了解一下向量叉积几何意义之一:

    有向量A(x1,y1),向量B(x2,y2),叉积结果A*B=x1y2-x2y1是一个标量,如果它等于0表示AB在同一直线上,大于0表示A在B的顺时针方向,小于0表示A在B的逆时针方向

    故而实现核心为通过向量叉积结果的正负判断点在直线的哪一侧,其它的处理就与点代一般式方法近似了.

3.ac代码

    (1).面积法

#include <stdio.h>
#include <math.h>
typedef long long ll;

void solve(){
	int t;
	scanf("%d",&t); 
	for(int i=0;i<t;i++){
		ll px,py,ax,ay,bx,by,cx,cy;
		scanf("%lld%lld%lld%lld%lld%lld%lld%lld",&px,&py,&ax,&ay,&bx,&by,&cx,&cy);
		//判断是否不在三角形内 
		if(fabs(px*(by-cy)+bx*(cy-py)+cx*(py-by))+fabs(ax*(py-cy)+px*(cy-ay)+cx*(ay-py))+fabs(ax*(by-py)+bx*(py-ay)+px*(ay-by))==fabs(ax*(by-cy)+bx*(cy-ay)+cx*(ay-by))) printf("YES\n");
		else printf("NO\n");
	}
	
}

int main(){
	solve();
	return 0;
}

    (2)点代一般式法

#include <stdio.h>
typedef long long ll;
struct point{ //(x,y)
	ll x,y;
};

struct line{ //ax+by+c=0
	ll a,b,c;
};

line getlinebytwopoint(point p1,point p2){ //已知两点求直线一般式 
	line res;
	res.a=p2.y-p1.y;
	res.b=p1.x-p2.x;
	res.c=p2.x*p1.y-p1.x*p2.y; 
	return res;
}

ll getpsbaseonline(point p,line l){ //将点带入一般式获知点在左上侧还是右下侧,大于0左上,等于0线上,小于0右下,返回值仅保留正负特征 
	ll temp=l.a*p.x+l.b*p.y+l.c;
	if(temp==0) return 0; 
	return temp>0?1:-1;
}

void solve(){
	int t;
	scanf("%d",&t); 
	for(int i=0;i<t;i++){
		point pointp,pointa,pointb,pointc;
		scanf("%lld%lld%lld%lld%lld%lld%lld%lld",&pointp.x,&pointp.y,&pointa.x,&pointa.y,&pointb.x,&pointb.y,&pointc.x,&pointc.y);
		line lineab,linebc,lineac;
		lineab=getlinebytwopoint(pointa,pointb);
		linebc=getlinebytwopoint(pointb,pointc);
		lineac=getlinebytwopoint(pointa,pointc);
		
		bool ans=true;
		//判断是否不在三角形内 
		if(getpsbaseonline(pointa,linebc)*getpsbaseonline(pointp,linebc)<0||getpsbaseonline(pointb,lineac)*getpsbaseonline(pointp,lineac)<0||getpsbaseonline(pointc,lineab)*getpsbaseonline(pointp,lineab)<0) ans=false;
		
		if(ans) printf("YES\n");
		else printf("NO\n");
	}
	
}

int main(){
	solve();
	return 0;
}

    (3)矢量法

#include <stdio.h>
typedef long long ll;

struct point{
	ll x,y;
};

struct myvector{
	ll x,y;
};

myvector getmyvectorbytwopoint(point p1,point p2){
	myvector res;
	res.x=p2.x-p1.x;
	res.y=p2.y-p1.y;
	return res;
}

ll getpsbaseonmyvector(point p,point p1,point p2){
	myvector p1p2=getmyvectorbytwopoint(p1,p2);
	myvector p1p=getmyvectorbytwopoint(p1,p);
	ll temp=p1p2.x*p1p.y-p1p.x*p1p2.y; //叉积结果 
	if(temp==0) return 0; 
	return temp>0?1:-1;
}


void solve(){
	int t;
	scanf("%d",&t);
	for(int i=0;i<t;i++){
		point pointp,pointa,pointb,pointc;
		scanf("%lld%lld%lld%lld%lld%lld%lld%lld",&pointp.x,&pointp.y,&pointa.x,&pointa.y,&pointb.x,&pointb.y,&pointc.x,&pointc.y);
		bool ans=true;
		
		//判断是否不在三角形内 
		if(getpsbaseonmyvector(pointa,pointb,pointc)*getpsbaseonmyvector(pointp,pointb,pointc)<0||getpsbaseonmyvector(pointb,pointa,pointc)*getpsbaseonmyvector(pointp,pointa,pointc)<0||getpsbaseonmyvector(pointc,pointa,pointb)*getpsbaseonmyvector(pointp,pointa,pointb)<0) ans=false;
		
		if(ans) printf("YES\n");
		else printf("NO\n");
	}
}

int main(){
	solve();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_31964727/article/details/83386878
今日推荐