hdu 6325 - 凸包面积

题目链接:点击这里

解题思路:

实际上是求从第一个点出发逆时针路径到达最后一个点的凸包,其实一个细节就是凸包上的点上,三点共线的中间那个点是否要删除?那就看他后面的那个点的下标是否小于它,小于的话删除之后字典序就更小了。

#include<bits/stdc++.h>
using namespace std;
const int mx = 2e5 + 10;
typedef long long ll;
int n,m,ans[mx],top,ma;
struct node
{
    int x,y;
    int pos;
}s[mx],tubeg[mx],w;
bool vis[mx];
ll judge(node p1,node p2,node p0)//面积公式判断正负值 
{
    ll ans = 1ll*(p1.x-p0.x)*(p2.y-p0.y) - 1ll*(p2.x-p0.x)*(p1.y-p0.y);
    return ans; 
}
bool cmp(node a,node b)
{
    ll c = judge(w,b,a);//极角排序,同角度按距离从小到大排 
    if(b.x==a.x&&b.y==a.y) return a.pos > b.pos;
    if(!c) return pow(a.x-w.x,2)+pow(a.y-w.y,2) < pow(b.x-w.x,2)+pow(b.y-w.y,2);
    return c > 0;
}
void Graham()
{
    tubeg[0] = s[0],tubeg[1] = s[1];
    top = 2;
    for(int i=2;i<n;i++)
    {
        while(top>1&&judge(tubeg[top-2],s[i],tubeg[top-1])<=0)
        {
            if(judge(tubeg[top-2],s[i],tubeg[top-1])<0||tubeg[top-1].pos>s[i].pos) top--;
            else break;
        }
        tubeg[top++] = s[i];
    }
    for(int i=0;i<top;i++) printf("%d%c",tubeg[i].pos+1,i==top-1?'\n':' ');
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++){
            scanf("%d%d",&s[i].x,&s[i].y);
            s[i].pos = i; 
        }
        w = s[0];
        sort(s+1,s+n,cmp);
        Graham();
    }
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/a1214034447/article/details/81430002