hiho225 Inside Triangle

目錄

題目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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章