UVALive 4617 Simple Polygon(顺/逆时针输出所有点/极角排序)

来源:互联网 发布:淘宝怎么预约快递 编辑:程序博客网 时间:2024/05/28 05:19

题目链接:
UVALive 4617 Simple Polygon
题意:
将平面所有点都用上,构成一个多边形,顺时针(或逆时针)输出点的顺序。
分析:
多边形有可能是凸的也有可能是凹的。
先找到最左下角的点(x值优先),然后对其余点以最左下角为基点极角排序。除去最左侧的一系列和point[0]共线的点,其余的点的顺序即是逆时针的点的顺序。

#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <climits>using namespace std;const int MAX_N=2010;const double eps=1e-10;int T,n;int ans[MAX_N];struct Point{    double x,y;    int index;    Point () {}    Point (double x,double y) : x(x),y(y) {    }    Point operator + (const Point& rhs) const{        return Point(x+rhs.x,y+rhs.y);    }    Point operator - (const Point& rhs) const {        return Point(x-rhs.x,y-rhs.y);    }    Point operator * (const double d) const {        return Point(d*x,d*y);    }    double dis(const Point& rhs) const{        return sqrt((x-rhs.x)*(x-rhs.x)+(y-rhs.y)*(y-rhs.y));    }    double dot(const Point& rhs) const{        return (x*rhs.x-y*rhs.y);    }    double cross(const Point& rhs) const{        return (x*rhs.y-y*rhs.x);    }}point[MAX_N];inline bool cmp(Point a,Point b){//按照最左下角极角排序    double res=(a-point[0]).cross(b-point[0]);    if(res!=0.0) return res>0;//res>0说明b在左侧,此时a的极角较小    else return a.dis(point[0])<b.dis(point[0]); //共线时按照距离从小到大排序}inline void solve(){    //找到最左下角顶点,优先x最小,其次y最小    int k=0;    for(int i=0;i<n;i++){        if(point[i].x<point[k].x||(point[i].x==point[k].x&&point[i].y<point[k].y)){            k=i;        }    }    swap(point[0],point[k]);    sort(point+1,point+n,cmp); //排序从下标1开始,因为point[0]就是起点    int end=n-2;    //找到最后的顶点end,使得point[end],point[end+1]和point[0]不共线    while(end>0){        double res=(point[end]-point[0]).cross(point[end+1]-point[0]);        if(res!=0.0) break;        end--;    }    //从point[end+1]到point[n-1]都是和point[0]共线的点,即point[end+1]..point[n-1],point[0]都在一条直线上    //因为极角排序时是按照到point[0]距离从小到大排序,所以这些点的逆时针顶点应该是按照距离从大到小考虑    //point[end+1]实际上应该是第n-1个点,point[n-1]实际上应该时第end+1个点    for(int i=end+1;i<n;i++){        ans[i]=point[n+end-i].index;    }    for(int i=0;i<=end;i++){        ans[i]=point[i].index;    }    for(int i=0;i<n;i++){        printf("%d%c",ans[i],i==n-1?'\n':' ');    }}int main(){    scanf("%d",&T);    while(T--){        scanf("%d",&n);        for(int i=0;i<n;i++){            scanf("%lf%lf",&point[i].x,&point[i].y);            point[i].index=i;        }        solve();    }    return 0;}
0 0
原创粉丝点击