poj 1228 Grandpa's Estate (穩定凸包)
阿新 • • 發佈:2018-12-21
題意:給出n個原來凸包的點,問能否根據這n個點推測出原來的凸包,若能,輸出YES。
題解:我們先求出這n個點的凸包來,然後在判斷新凸包每條邊都有其它點在,那麼可以說明此邊是確定邊,因為要想讓一個凸包穩定,當且僅當凸包上任意一條邊有3個以上的木樁(包括端點)。
例如這圖,假設新凸包點為A,C,D,很容易可以看到CD邊沒有其它點,那麼這條邊就是不確定的,它有可能還有個F點(這個點未知)。
還注意一點的是: 小於6個點,一定不能成穩定凸包,因為最小是三角形的凸包,每條邊之間有一個點,那麼這都有六個點了。
#include<algorithm> #include<cstring> #include<cstdio> #include<cmath> using namespace std; const int maxn=1010; struct point{ int x,y; point(){} point(int _x,int _y){ x=_x;y=_y; } }p[maxn],ch[maxn]; int n; point operator + (point a,point b) { return point(a.x+b.x,a.y+b.y);} point operator - (point a,point b) { return point(a.x-b.x,a.y-b.y);} point operator * (point a,int p) { return point(a.x*p,a.y*p);} point operator / (point a,int p) { return point(a.x/p,a.y/p);} bool operator < (const point &a,const point &b){ return a.x<b.x||(a.x==b.x&&a.y<b.y); } const double esp=1e-8; int dcmp(double x) { if(fabs(x)<esp) return 0; else return x<0?-1:1; } bool operator == (const point &a,const point b){ return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0; } int Cross(point a,point b) { return a.x*b.y-a.y*b.x;} int Dot(point a,point b) { return a.x*b.x+a.y*b.y;} bool cmp(point a,point b){ return (a.y<b.y||(a.y==b.y&&a.x<b.x)); } int tot; void andrew(int n) { sort(p,p+n,cmp); tot=-1; for(int i=0;i<n;i++) { while(tot>0&&Cross(ch[tot]-ch[tot-1],p[i]-ch[tot])<=0) tot--; ch[++tot]=p[i]; } for(int i=n-2,k=tot;i>=0;i--) { while(tot>k&&Cross(ch[tot]-ch[tot-1],p[i]-ch[tot-1])<=0) tot--; ch[++tot]=p[i]; } } ///判斷點線上段上(不包括端點) bool Onsegment(point p,point a1,point a2) { return dcmp(Cross(a1-p,a2-p))==0&&dcmp(Dot(a1-p,a2-p))<0; } bool judge(point a,point b) ///判斷ab邊是否穩定 { for(int i=0;i<n;i++){ if(Onsegment(p[i],a,b)) return true; } return false; } int main() { int ncase; scanf("%d",&ncase); while(ncase--) { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d%d",&p[i].x,&p[i].y); if(n<6){ ///小於6個點,一定不能組成穩定的凸包 puts("NO");continue; } andrew(n); ///根據這n個點構造凸包 bool flag=true; for(int i=1;i<=tot&&flag;i++) { if(!judge(ch[i],ch[i-1])){ ///判斷ch[i]ch[i-1]這條邊是否穩定 flag=false;break; } } if(flag) puts("YES"); else puts("NO"); } return 0; }