1. 程式人生 > >[poj] 1228 Grandpa's Estate || 穩定凸包

[poj] 1228 Grandpa's Estate || 穩定凸包

swa int ble std %d rand += def amp

原題

判斷給出點形成的凸包是否穩定(點保證在凸包上)
穩定:無法形成一個新的凸包仍使這些點在凸包上(即每條邊上的點至少有3個)


先求出凸包,然後判斷每條邊上的點是否大於2個

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 1010
using namespace std;
int t,n,m,per[N];
struct point
{
    int x,y;
    point() {}
    point(int _x,int _y) : x(_x),y(_y) {}
    point operator
- (const point &b) const { return point(b.x-x,b.y-y); } int operator * (const point &b) const { return x*b.y-b.x*y; } bool operator < (const point &b) const { if (x==b.x) return y<b.y; return x<b.x; } int norm() { return
x*x+y*y; } }p[N],q[N]; int dot(point a,point b) { return a.x*b.x+a.y*b.y; } struct Line { point a,b; int cnt; void init(point x,point y) { a=x; b=y; cnt=0; } int online(point k) { int d=(a-k)*(b-k); if (d!=0) return 0; if
(dot(a-k,b-k)>0) return 0; return 1; } }line[N]; bool cmp(int i,int j) { int d=(p[i]-p[1])*(p[j]-p[1]); if (d!=0) return d>0; return (p[i]-p[1]).norm()<(p[j]-p[1]).norm(); } void Graham() { int id=1; for (int i=2;i<=n;i++) if (p[i]<p[id]) id=i; if (id!=1) swap(p[1],p[id]); for (int i=1;i<=n;i++) per[i]=i; sort(per+2,per+n+1,cmp); q[++m]=p[1]; for (int i=2,j;i<=n;i++) { j=per[i]; while (m>=2 && (p[j]-q[m-1])*(q[m]-q[m-1])>=0) m--; q[++m]=p[j]; } } bool solve() { q[m+1]=q[1]; for (int i=1;i<=m;i++) line[i].init(q[i],q[i+1]); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) line[j].cnt+=line[j].online(p[i]); for (int i=1;i<=m;i++) if (line[i].cnt<=2) return 1; return 0; } int main() { scanf("%d",&t); while (t--) { scanf("%d",&n); m=0; for (int i=1;i<=n;i++) scanf("%d%d",&p[i].x,&p[i].y); Graham(); if (m<=2 || solve()) puts("NO"); else puts("YES"); } return 0; }

[poj] 1228 Grandpa's Estate || 穩定凸包