原题
判断给出点形成的凸包是否稳定(点保证在凸包上)
稳定:无法形成一个新的凸包仍使这些点在凸包上(即每条边上的点至少有3个)
先求出凸包,然后判断每条边上的点是否大于2个
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 1010
using namespace std;
int t,n,m,per[N];
struct point
{
int x,y;
point() {}
point(int _x,int _y) : x(_x),y(_y) {}
point operator - (const point &b) const
{
return point(b.x-x,b.y-y);
}
int operator * (const point &b) const
{
return x*b.y-b.x*y;
}
bool operator < (const point &b) const
{
if (x==b.x) return y<b.y;
return x<b.x;
}
int norm()
{
return x*x+y*y;
}
}p[N],q[N];
int dot(point a,point b)
{
return a.x*b.x+a.y*b.y;
}
struct Line
{
point a,b;
int cnt;
void init(point x,point y)
{
a=x;
b=y;
cnt=0;
}
int online(point k)
{
int d=(a-k)*(b-k);
if (d!=0) return 0;
if (dot(a-k,b-k)>0) return 0;
return 1;
}
}line[N];
bool cmp(int i,int j)
{
int d=(p[i]-p[1])*(p[j]-p[1]);
if (d!=0) return d>0;
return (p[i]-p[1]).norm()<(p[j]-p[1]).norm();
}
void Graham()
{
int id=1;
for (int i=2;i<=n;i++)
if (p[i]<p[id]) id=i;
if (id!=1) swap(p[1],p[id]);
for (int i=1;i<=n;i++) per[i]=i;
sort(per+2,per+n+1,cmp);
q[++m]=p[1];
for (int i=2,j;i<=n;i++)
{
j=per[i];
while (m>=2 && (p[j]-q[m-1])*(q[m]-q[m-1])>=0)
m--;
q[++m]=p[j];
}
}
bool solve()
{
q[m+1]=q[1];
for (int i=1;i<=m;i++)
line[i].init(q[i],q[i+1]);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
line[j].cnt+=line[j].online(p[i]);
for (int i=1;i<=m;i++)
if (line[i].cnt<=2) return 1;
return 0;
}
int main()
{
scanf("%d",&t);
while (t--)
{
scanf("%d",&n);
m=0;
for (int i=1;i<=n;i++)
scanf("%d%d",&p[i].x,&p[i].y);
Graham();
if (m<=2 || solve())
puts("NO");
else puts("YES");
}
return 0;
}