题意:给你一堆点,问你这些点能否唯一构成一个凸包;
知识点:凸包上的每一条边至少由三个点确定
还有,我求凸包求出来的是封闭图形,会有两个起始点
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define inf 0x7ffffff
using namespace std;
const double eps=1e-8;
struct P
{
double x,y;
P (){}
P (double x,double y):x(x),y(y){
}
P operator +(P p){
return P(x+p.x,y+p.y);
}
P operator -(P p){
return P(x-p.x,y-p.y);
}
P operator *(double d){
return P(x*d,y*d);
}
double det(P p){
return x*p.y-y*p.x;
}
double dot(P p){
return x*p.x+y*p.y;
}
};
bool cmp(P a,P b)
{
if(a.x!=b.x)
return a.x<b.x;
return a.y<b.y;
}
P p[100000],qs[1000000];
int t,n,k;
bool on_seg(P a,P b,P c)
{
return ((a-c).det(a-b)==0 && (a-c).dot(b-c)<=0);
}
int main()
{
scanf("%d",&t);
while(t--)
{
k=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
sort(p,p+n,cmp);
for(int i=0;i<n;i++)
{
while(k>1 && (qs[k-1]-qs[k-2]).det(p[i]-qs[k-2])<=0) k--;
qs[k++]=p[i];
}
for(int i=n-1,t=k;i>=0;i--)
{
while(k>t && (qs[k-1]-qs[k-2]).det(p[i]-qs[k-2])<=0) k--;
qs[k++]=p[i];
}
int fg=1;
/* for(int i=0;i<k;i++)
{
printf("%lf %lf\n",qs[i].x,qs[i].y);
}*/
if(k<=3)
{
printf("NO\n");
continue;
}
for(int i=0;i<k-1;i++)
{
int ans=0;
for(int j=0;j<n;j++)
{
if(on_seg(qs[i],qs[i+1],p[j]))
ans++;
}
if(ans<3)
{
fg=0;
break;
}
}
if(fg)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}