poj1228 Grandpa's Estate
题目描述:
题目大意:给出多组多边形,判断用上所有节点的前提下能否确定一个凸包。
题解:
$n<3$时,一定不能……
$n \geq 3$时,建出凸包,判断凸包点数是否与给出点数相等。
确定一个凸包=每条边上至少有三个节点。
代码:
#include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; const int N = 1050; const double eps = 1e-8; int dcmp(double x) { if(fabs(x)<=eps)return 0; return x>0?1:-1; } struct Point { double x,y; Point(){} Point(double x,double y):x(x),y(y){} Point operator - (const Point&a)const{return Point(x-a.x,y-a.y);} double operator ^ (const Point&a)const{return x*a.y-y*a.x;} bool operator < (const Point&a)const{return x!=a.x?x<a.x:y<a.y;} }; typedef Point Vector; int T,n; Point p[N],s[N]; int build() { sort(p+1,p+1+n); int tl = 0; for(int i=1;i<=n;i++) { while(tl>1&&((p[i]-s[tl-1])^(s[tl]-s[tl-1]))>0)tl--; s[++tl] = p[i]; } int k = tl; for(int i=n-1;i>=1;i--) { while(tl>k&&((p[i]-s[tl-1])^(s[tl]-s[tl-1]))>0)tl--; s[++tl] = p[i]; } if(tl!=1)tl--; return tl; } void work() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); int m = build(),i,j; if(m!=n||n<3) { puts("NO"); return ; } s[m+1] = s[1]; for(i=1;i<=m;i=j) { j = i+1; while(j<=m&&!dcmp((s[j+1]-s[j])^(s[j]-s[i])))j++; if(j==i+1) { puts("NO"); return ; } } puts("YES"); return ; } int main() { // freopen("tt.in","r",stdin); scanf("%d",&T); while(T--)work(); return 0; }