题目:
给你n个点,保证这些点都在凸包上(顶点或者边上),问这个凸包是不是一个稳定的凸包,
稳定被定义为:
存在一个点使得原来的点都在包含该点和原来的点的凸包上
题解:
题目中的要求等价于问每条边上的点超没超过三个
如果存在不够三个的就不是稳定的
Graham算法保证只求凸包的顶点,所以我们可以枚举凸包的每条边和每个点判断这个边上的点超没超过3个
n2的辣鸡算法
#include<cstdio> #include<algorithm> #include<cstring> #define N 1010 using namespace std; int T,n,m; struct point { int x,y; point (){}; point (int _x,int _y) { x=_x; y=_y; } point operator - (const point &a)const { return point(x-a.x,y-a.y); } int operator * (const point &a)const { return x*a.y-y*a.x; } int norm() { return x*x+y*y; } }p[N],q[N]; int dot(const point &a,const point &b) { return a.x*b.x+a.y*b.y; } int Area(const point &x,const point &y,const point &z) { return (y-x)*(z-x); } struct line { point a,b; int cnt; int Inline(const point &k) { int det=(a-k)*(b-k); if (det!=0) return 0; if (dot(a-k,b-k)>0) return 0; return 1; } }li[N]; bool cmp(int u,int v) { int det=(p[u]-p[1])*(p[v]-p[1]); if (det!=0) return det>0; return (p[u]-p[1]).norm()<(p[v]-p[1]).norm(); } void Graham() { int id=1; for (int i=2;i<=n;i++) if (p[i].x<p[id].x || (p[i].x==p[id].x && p[i].y<p[id].y)) id=i; if (id!=1) swap(p[id],p[1]); int per[N]; for (int i=1;i<=n;i++) per[i]=i; sort(per+2,per+1+n,cmp); q[++m]=p[1]; for (int i=2;i<=n;i++) { int j=per[i]; while (m>=2 && (p[j]-q[m-1])*(q[m]-q[m-1])>=0) m--; q[++m]=p[j]; } } bool solve() { bool ret=0; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { li[j].cnt+=li[j].Inline(p[i]); } for (int i=1;i<=m;i++) if (li[i].cnt<=2) ret=1; return ret; } 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(); // for (int i=1;i<=m;i++) // printf("On %d %d ",q[i].x,q[i].y); q[m+1]=q[1]; for (int i=1;i<=m;i++) li[i].a=q[i],li[i].b=q[i+1],li[i].cnt=0; if (solve() || m<=2) puts("NO"); else puts("YES"); } return 0; }