POJ - 1228 Grandpa's Estate
题目链接:https://vjudge.net/problem/POJ-1228
题意:给你一堆点,这堆点本来就是某个凸包上的部分点,问你这堆点是否能确定唯一的凸包,这种凸包叫做稳定凸包。
稳定凸包的含义:当凸包上存在一条边上的点只有端点两个点的时候,这个凸包不是稳定的,因为它可以在这条边外再引入一个点,构成一个新的凸包。
但一旦一条边上存在三个点,那么不可能再找到一个点使它扩展成一个新的凸包,否则构成的新多边形将是凹的。
思路:先根据给定的点求出凸包,在求凸包时,不需要把斜率一样位置近的点去掉。然后再看求出凸包的点上是否每条线上至少有三个点就可以了。
#include<bits/stdc++.h> #include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<map> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const double PI = atan(1.0)*4.; const int maxn=200005; struct point { double x,y; point friend operator -(point A,point B) { return {A.x-B.x,A.y-B.y}; } }; struct line { point x,y; }; point p[maxn];//输入点集 point q[maxn];//凸包点集 double dis(point A,point B)//两点的距离 { return sqrt( (A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y) ); } double chaj(point A,point B)//差积 { return A.x*B.y-A.y*B.x; } bool cmp(point A,point B)//以p[0]为起点,按差积逆时针排序 { double s=chaj(A-p[1],B-p[1]); if(s>0) return true; if(s==0) return dis(A,p[1])<dis(B,p[1]); return false; } int main() { int T; cin>>T; while(T--) { int N; cin>>N; for(int i=1; i<=N; i++) cin>>p[i].x>>p[i].y; if(N<6) { cout<<"NO"<<endl; continue; } //找到最小的点 int K=1; for(int i=2; i<=N; i++) { if(p[i].y<p[K].y||(p[i].y==p[K].y&&p[i].x<p[K].x)) K=i; } swap(p[1],p[K]); sort(p+2,p+1+N,cmp); q[1]=p[1]; q[2]=p[2]; int len=2;//凸包点的个数 for(int i=3; i<=N; i++) { while(len>=2&&chaj(q[len]-q[len-1],p[i]-q[len-1])<0) len--; q[++len]=p[i]; } q[++len]=q[1]; int flag=1; for(int i=3;i<len;i++) { if(chaj(q[i-1]-q[i-2],q[i]-q[i-1])!=0&&chaj(q[i]-q[i-1],q[i+1]-q[i])!=0) flag=0; } if(flag) cout<<"YES"<<endl; else cout<<"NO"<<endl; } }