nyoj 78:圈水池 【凸包入门】

题目链接

将所有点按从左至右顺序排序,然后将所有点先从左到右扫描再从右到左扫描,逐渐将凸包轮廓“勾勒”出来

(凸包轮廓满足,轮廓上连续的三个点按先后顺序给出的话呈逆时针方向)

最后删去一个重复的起(终)点

 
#include<bits/stdc++.h>
using namespace std;

struct point
{
    double x,y;
    point operator -(const point& rhs)const
    {
        point ret;
        ret.x=x-rhs.x;
        ret.y=y-rhs.y;
        return ret;
    }
    double operator *(const point& rhs)const//叉乘
    {
        return x*rhs.y-y*rhs.x;
    }
    bool operator <(const point& rhs)const
    {
        return x<rhs.x||x==rhs.x&&y<rhs.y;
    }
}p[105],s[105];

bool ok(point A,point B,point C)    //判断ABC是否是按逆时针顺序给出 
{
    return (B-A)*(C-A)>0;
}

int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        sort(p,p+n);
        
        int top=0;
        for(int i=0;i<n;i++)    //求下凸包
        {
            while(top>=2 && !ok(s[top-2],s[top-1],p[i]))
                top--;
            s[top++]=p[i];
        }
        int t=top-1;
        for(int i=n-1;i>=0;i--)    //求上凸包
        {
            while(top>=t+2 && !ok(s[top-2],s[top-1],p[i]))
                top--;
            s[top++]=p[i];
        }
        --top;    //    首尾点相同,故舍去 
        sort(s,s+top);
        for(int i=0;i<top;i++)
            printf("%.0lf %.0lf\n",s[i].x,s[i].y); 
    }
}        

 

转载于:https://www.cnblogs.com/Just--Do--It/p/6413756.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值