Light OJ 1203 凸包+寻找凸多边形最小角度

来源:互联网 发布:国云大数据魔镜 编辑:程序博客网 时间:2024/05/21 10:13

题目的意思不难理解,就是求凸包中最小角度
首先构造凸包,之后求最小的角度(<180)
注意有一个陷阱,当角度为180度时,假设图形中仅仅只有一个点,实际的角度应该是0度,这点需要特判.
WA了一天才发现.

#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>const double PI=acos(-1);const int maxn=1e5+10;const double INF=180;const double eps=1e-10;int n;int top;using namespace std;int sgn(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;    }};typedef point vector;vector operator- (point a,point b){    return point(a.x-b.x,a.y-b.y);}double operator * (vector a,vector b){    return a.x*b.x+a.y*b.y;}double operator ^ (vector a,vector b){    return a.x*b.y-a.y*b.x;}bool operator < (point a,point b){    return a.x==b.x && a.y<b.y ||a.x<b.x;}double dis(point a,point b){    return hypot(a.x-b.x,a.y-b.y);}point p[maxn];point stack[maxn];bool cmp(point a,point b){    int d=sgn((a-p[0])^(b-p[0]));    return d>0 || d==0 && sgn(dis(a,p[0])-dis(b,p[0]))<0;}double len(vector a){    return hypot(a.x,a.y);}double Angle(point a,point b,point p){    vector A=p-a;    vector B=p-b;    return 360.0/(2*PI)*acos((A*B)/(len(A)*len(B)));}void graham(){   //不需要考虑n=1和n=2的情况    stack[0]=p[0];    stack[1]=p[1];    top=2;    for(int i=2;i<n;i++){        while(top>1&&sgn((stack[top-1]-stack[top-2])^(p[i]-stack[top-2]))<=0 )            top--;        stack[top]=p[i];        top++;    }}double solve(){          //graham-scan    for(int i=0;i<n;i++)        if(p[i]<p[0])    swap(p[0],p[i]);    sort(p+1,p+n,cmp);//极角排序    graham();    double min=INF;    for(int i=0;i<top;i++){        if(Angle(stack[(i-1+top)%top],stack[(i+1)%top],stack[i]) < min)            min=Angle(stack[(i-1+top)%top],stack[(i+1)%top],stack[i]);    }    return min;}int main(){    //freopen("input1203.txt","r",stdin);    int T,cnt=0;    scanf("%d",&T);    while(T--){        double angle;        scanf("%d",&n);        for(int i=0;i<n;i++)            scanf("%lf%lf",&p[i].x,&p[i].y);        if(n==1||n==2)            angle=0;        else            angle=solve();        if(sgn(angle-180.0)==0) //特判            angle=0;        printf("Case %d: %.7lf\n",++cnt,angle);    }}
0 0
原创粉丝点击