给题意跪了。。。
题目输入一个凸包上的点(没有凸包内部的点,要么是凸包顶点,要么是凸包边上的点),判断这个凸包是否稳定。所谓稳定就是判断能不能在原有凸包上加点,
得到一个更大的凸包,并且这个凸包包含原有凸包上的所有点。
这样,只需判断每条边是否有大于等于三点即可。注意,一条直线的凸包是NO
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; struct point { int x,y; }p[1050]; int n; int stop,cnt; int ans[1050],st[1050]; bool cmp(point A,point B){ if(A.y<B.y) return true; else if(A.y==B.y){ if(A.x<B.x) return true; } return false; } bool multi(point a,point b,point c){ return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x)>0; } void slove(){ stop=cnt=0; st[stop++]=0; st[stop++]=1; for(int i=2;i<n;i++){ while(stop>1&&multi(p[i],p[st[stop-1]],p[st[stop-2]])) stop--; st[stop++]=i; } for(int i=0;i<stop;i++) ans[cnt++]=st[i]; stop=0; st[stop++]=n-1; st[stop++]=n-2; for(int i=n-3;i>=0;i--){ while(stop>1&&multi(p[i],p[st[stop-1]],p[st[stop-2]])) stop--; st[stop++]=i; } for(int i=1;i<stop;i++) ans[cnt++]=st[i]; } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d%d",&p[i].x,&p[i].y); } sort(p,p+n,cmp); slove(); /* for(int i=0;i<cnt;i++){ cout<<p[ans[i]].x<<‘ ‘<<p[ans[i]].y<<endl; }*/ if(n==1||n==2) { printf("NO\n"); continue; } bool flag=true; point s,t,e; int k; s=p[ans[0]]; t=p[ans[1]]; int j; for(j=2;j<cnt;j++){ e=p[ans[j]]; if((e.x-s.x)*(t.y-s.y)-(e.y-s.y)*(t.x-s.x)!=0){ break; } } if(j>=cnt) { printf("NO\n"); continue; } for(int i=0;;i=k-1){ s=p[ans[i]];t=p[ans[++i]]; if(i+1>=cnt){ flag=false; break; } e=p[ans[i+1]]; if((e.x-s.x)*(t.y-s.y)-(e.y-s.y)*(t.x-s.x)!=0){ flag=false; break; } k=i+1; while(true){ e=p[ans[k]]; if((e.x-s.x)*(t.y-s.y)-(e.y-s.y)*(t.x-s.x)!=0){ break; } k++; if(k>=cnt) break; } if(k>=cnt) break; } if(flag) printf("YES\n"); else printf("NO\n"); } return 0; }
时间: 2024-11-18 03:09:31