1. 程式人生 > 實用技巧 >POJ - 1228 Grandpa's Estate

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; } }