码迷,mamicode.com
首页 > 编程语言 > 详细

2018杭电多校第三场1007(凸包,极角排序)

时间:2018-08-24 13:15:32      阅读:126      评论:0      收藏:0      [点我收藏+]

标签:++   参与   杭电多校   距离   顺序   排序   scanf   str   字典序   

#include<bits/stdc++.h>
using namespace std;
typedef const long long ll;
struct node
{
    int x,y;
    int pos;
}plane[200020],tubao[200020],stt;
int top;
int n;
long long multi(node a,node b,node c)
{
    ll mianji=1ll*(a.x-c.x)*(b.y-c.y)-1ll*(a.y-c.y)*(b.x-c.x);//面积公式判断正负值
    return mianji;
}
bool cmp(node a,node b)
{
    if(a.x==b.x&&a.y==b.y)
        return a.pos>b.pos;//重复点,字典序大的排在前(此处如果将字典序小的排在前,则WA,原因未知)
    if(!multi(stt,b,a))//两个点与原点的连线斜率相等,即三点共线
        return pow(a.x-stt.x,2)+pow(a.y-stt.y,2)<pow(b.x-stt.x,2)+pow(b.y-stt.y,2);
        //和原点距离近的排在前
    return multi(stt,b,a)>0;//multi为正说明联接凸包的顺序a在b之前(a在b下面如果纵坐标相等a横坐标更小)
}
void graham()
{
    tubao[1]=plane[1];
    tubao[2]=plane[2];
    top=3;
    for(int i=3;i<=n;i++)
    {
        while(top>2&&multi(tubao[top-2],plane[i],tubao[top-1])<=0)
        {
            if(multi(tubao[top-2],plane[i],tubao[top-1])<0||plane[i].pos<tubao[top-1].pos)//处理字典序问题
                //该点应在栈中第二点之前联接凸包或者和第二点重合然而字典序靠前
                top--;
            else
                break;
        }
        tubao[top++]=plane[i];//用栈模拟联接凸包顺序
    }
    for(int i=1;i<top;i++)
    {
        printf("%d%c",tubao[i].pos,i==top-1?‘\n‘:‘ ‘);
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        int x,y;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&x,&y);
            plane[i].x=x;
            plane[i].y=y;
            plane[i].pos=i;
        }
        stt=plane[1];
        sort(plane+2,plane+1+n,cmp);//起点不参与排序
        graham();
    }
    return 0;
}

//坐标排序待补

2018杭电多校第三场1007(凸包,极角排序)

标签:++   参与   杭电多校   距离   顺序   排序   scanf   str   字典序   

原文地址:https://www.cnblogs.com/ldudxy/p/9528928.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!