Atcoder Beginner Contest 266 problem C 题解
题目链接:点我
题目大意
以逆时针顺序给定平面上四个点 ( A x , A y ) , ( B x , B y ) , ( C x , C y ) , ( D x , D y ) (A_x,A_y),(B_x,B_y),(C_x,C_y),(D_x,D_y) (Ax,Ay),(Bx,By),(Cx,Cy),(Dx,Dy),求这四个点组成的四边形是否为凸四边形。
样例输入1
0 0
1 0
1 1
0 1
样例输出1
Yes
样例解释1
该四边形是一个正方形,显然是凸四边形。
样例输入2
0 0
1 1
-1 0
1 -1
样例输出2
No
样例解释2
数据范围
所有坐标数字均为整数且在 [ − 100 , 100 ] [-100,100] [−100,100]范围内。
解析
本蒟蒻用了自己想出的通俗解法。
这道题的关键其实就在于如何判断一个点是否在其他三个点所组成的三角形内部。如果四个顶点都不满足上面的条件,那么这一定是一个凸四边形。
对于样例2,点 A A A处在 Δ B C D \Delta BCD ΔBCD所形成的三角形内部,因此这个四边形是凹四边形。
那么如何去判断呢?
其实不难发现,对于四边形中的每一个点,如果它和其他三个点组成的四边形的面积(原四边形的面积)如果 ≤ \leq ≤其他三个点所组成的三角形的面积的话,那么这个点一定在其他三点所组成的三角形内部。
对于这一步,其实还有更简单的写法。这里本蒟蒻使用了海伦公式,写起来算是比较简便的了。
海伦公式: p = a + b + c 2 , 则 S = p ( p − a ) ( p − b ) ( p − c ) p=\frac{a+b+c}{2},则S=\sqrt{p(p-a)(p-b)(p-c)} p=2a+b+c,则S=p(p−a)(p−b)(p−c)
代码实现
大佬勿喷~
#include<iostream>
#include<cmath>
#include<vector>
using namespace std;
double x[5],y[5];
double dist[5][5];
inline double s(double a,double b,double c){//海伦公式计算面积
double p=(a+b+c)/2.0;
return sqrt(p*(p-a)*(p-b)*(p-c));
}
inline double dis(double x,double y,double a,double b){//计算两点之间的距离
double r1=x-a,r2=y-b;
return sqrt(r1*r1+r2*r2);
}
int main()
{
for(int i=0;i<4;i++)
cin>>x[i]>>y[i];
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
if(i!=j)
dist[i][j]=dis(x[i],y[i],x[j],y[j]);//预处理出两点之间的距离
for(int i=0;i<4;i++){
vector<int>v;v.clear();
double S=0,res;
v.push_back((i-1+4)%4);
v.push_back((i-2+4)%4);
v.push_back((i+1)%4);//找到其他的三个点
//值得注意的是,题目中给定了这四个点是按逆时针顺序给出的,所以我们可以直接按顺序存下其他的三个点(一定要按顺序,不然算面积时会算成其他三角形的面积)。
res=s(dist[v[0]][v[1]],dist[v[1]][v[2]],dist[v[0]][v[2]]);//其他三个点所组成的三角形的面积
for(int j=0;j<2;j++)
S+=s(dist[i][v[j]],dist[i][v[j+1]],dist[v[j]][v[j+1]]);//这个点与其他三个点所组成的四边形的面积
if(S-res<=1e-9){
cout<<"No";
return 0;//判断
}
}
cout<<"Yes";
}
(ps:以一般理性而言,这个点与其他三个点所组成的四边形的面积一定是原四边形的面积,可是省去31,32行直接写原四边形的面积的话就WA了,求大佬指正qwq)
完结撒花~~~