1. 程式人生 > >2018杭電多校第三場1007(凸包,極角排序)

2018杭電多校第三場1007(凸包,極角排序)

棧模擬 include struct node 距離 然而 bit const 極角

#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(凸包,極角排序)