题目大意:给你一个凸包上的某些点(可能在凸包内),询问是否能确定这个凸包。
思路:先求出题目给出的点的凸包,看看在凸包的每条边内(不包括端点)有没有点,若有,则这条边是确定的,若没有,则这条边不确定,直接输出NO。这里用Andrew求凸包。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; struct point{ double x,y; point(double x=0,double y=0):x(x),y(y){} }a[1001],ch[1001]; point operator - (point a,point b){ return point(a.x-b.x,a.y-b.y); } int i,j,k,n,m,t; double cross(point a,point b){ return a.x*b.y-a.y*b.x; } bool cmp(point a,point b){ return a.x<b.x||(a.x==b.x&&a.y<b.y)?1:0; } bool check(point a,point b){ return a.x!=b.x||a.y!=b.y?1:0; } int main() { scanf("%d",&t); for(int p=0;p<t;p++){ m=0; scanf("%d",&n); for(i=1;i<=n;i++)scanf("%lf%lf",&a[i].x,&a[i].y); if(n<6){ printf("NO "); continue; } sort(a+1,a+n+1,cmp); for(i=1;i<=n;i++){ while(m>1&&cross(ch[m]-ch[m-1],a[i]-ch[m-1])<=0)m--; ch[++m]=a[i]; } k=m; for(i=n-1;i>=1;i--){ while(m>k&&cross(ch[m]-ch[m-1],a[i]-ch[m-1])<=0)m--; ch[++m]=a[i]; } for(i=1;i<m;i++){ for(j=1;j<=n;j++) if(check(ch[i],a[j])&&check(ch[i+1],a[j])) if(((a[j].x>=ch[i].x&&a[j].x<=ch[i+1].x)||(a[j].x<=ch[i].x&&a[j].x>=ch[i+1].x))&&!cross(ch[i+1]-ch[i],a[j]-ch[i]))break; if(j==n+1)break; } if(i<m)printf("NO ");else printf("YES "); } return 0; }