题目链接
题目描述
判断一个点与已知三角形的位置关系。
输入输出格式
输入格式:
前三行:每行一个坐标,表示该三角形的三个顶点
第四行:一个点的坐标,试判断该点与前三个点围成三角形的位置关系
(详见样例)
所有坐标值均为整数。
输出格式:
若点在三角形内(不含边界),输出1;
若点在三角形外(不含边界),输出2;
若点在三角形边界上(不含顶点),输出3;
若点在三角形顶点上,输出4。
输入输出样例
输入样例#1:
(0,0)
(3,0)
(0,3)
(1,1)
输出样例#1:
1
法一:面积法
连结第四个点和三角形的三个顶点,得到三个三角形,若这三个三角形的面积之和等于原三角形面积,则该点在三角形内。
其他情况相应特判即可。
Code
#include
#define eps 1e-6
using namespace std;
double dist(int x1, int y1, int x2, int y2) {
return sqrt(pow(x2-x1,2) + pow(y2-y1,2));
}
double area(int x1, int y1, int x2, int y2, int x3, int y3) {
double a = dist(x1,y1,x2,y2), b = dist(x1,y1,x3,y3), c = dist(x2,y2,x3,y3);
double p = (a+b+c)/2;
return sqrt(p*(p-a)*(p-b)*(p-c));
}
int main() {
int x1,y1,x2,y2,x3,y3,x,y;
scanf("(%d,%d)\n(%d,%d)\n(%d,%d)\n(%d,%d)", &x1, &y1, &x2, &y2, &x3, &y3, &x, &y);
if ((x==x1&&y==y1) || (x==x2&&y==y2) || (x==x3&&y==y3)) { putchar('4'); return 0; }
double s1 = area(x1,y1,x2,y2,x,y),
s2 = area(x1,y1,x3,y3,x,y),
s3 = area(x3,y3,x2,y2,x,y),
s = area(x1,y1,x2,y2,x3,y3);
if (s1+s2+s3-s>eps) { putchar('2'); return 0; }
if (fabs(s1)
法二:叉积法
理论依据:
\(\overrightarrow{P0P1}\times \overrightarrow{P0P2}\gt 0\leftrightarrow P1在P2的顺时针方向(相对P0)\)
\(\overrightarrow{P0P1}\times \overrightarrow{P0P2}\lt 0\leftrightarrow P1在P2的逆时针方向(相对P0)\)
\(\overrightarrow{P0P1}\times \overrightarrow{P0P2}= 0\leftrightarrow P1,P2,P0三点共线\)
仍然连结第四个点和三角形的三个顶点,算出三个叉积,如果同正或同负,则在三角形内;
如果有一个为\(0\),另两个同号,则在三角形边上。
Code
#include
#define eps 1e-6
using namespace std;
int vec(int x1, int y1, int x2, int y2, int x0, int y0) {
return (x1-x0) * (y2-y0) - (x2-x0) * (y1-y0);
}
int main() {
int x1,y1,x2,y2,x3,y3,x,y;
scanf("(%d,%d)\n(%d,%d)\n(%d,%d)\n(%d,%d)", &x1, &y1, &x2, &y2, &x3, &y3, &x, &y);
if ((x==x1&&y==y1) || (x==x2&&y==y2) || (x==x3&&y==y3)) { putchar('4'); return 0; }
int c1 = vec(x1, y1, x2, y2, x, y),
c2 = vec(x2, y2, x3, y3, x, y),
c3 = vec(x3, y3, x1, y1, x, y);
if ((c1>0&&c2>0&&c3>0) || (c1<0&&c2<0&&c3<0)) { putchar('1'); return 0; }
if ((c1==0&&c2*c3>0) || (c2==0&&c1*c3>0) || (c3==0&&(c1*c2>0))) putchar('3');
else putchar('2');
return 0;
}