Surround the Trees

#include<iostream>
#include<cmath>
using namespace std;
struct Point
{
    double x, y;
};
const int MAXN=105;
Point p[MAXN];    //存放所有的点
Point result[MAXN];    //存放凸包上的点
int top;
double xmult(Point a, Point b, Point c)
{
    return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}
double dist(Point a, Point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int cmp(const void *a, const void *b)    //以左下角的点为基点,其它点与该点的连线与x轴所成的角度,从小到大排序
{
    Point p1=*(Point*)a;
    Point p2=*(Point*)b;
    double x=xmult(p[0], p1, p2);
    if (x<0) return 1;
    if (x==0 && dist(p[0], p1)<dist(p[0], p2)) return 1;
    return -1;
}
void create_convex(int n)    //生成凸包
{
    result[0]=p[0];
    result[1]=p[1];
    result[2]=p[2];
    int i;
    top=2;
    for (i=3; i<=n; i++)
    {
        while (xmult(result[top-1], result[top], p[i])<=0 && top>=1) top--;
        result[++top]=p[i];
    }
}
int main()
{
    int n;
    while (cin>>n, n)
    {


        int i;
        for (i=0; i<n; i++)
        {
            cin>>p[i].x>>p[i].y;
        }


        if (n==1) 
        {
            puts("0.00");
            continue;
        }
        if (n==2)
        {
            double len=dist(p[0], p[1]);
            printf("%.2lf\n", len);
            continue;
        }


        Point tmp;
        int pos=0;
        tmp.x=p[0].x; tmp.y=p[0].y;
        for (i=1; i<n; i++)        //寻找左下角的点
        {
            if (p[i].y<tmp.y)
            {
                tmp.x=p[i].x;
                tmp.y=p[i].y;
                pos=i;
            }
            if (p[i].y==tmp.y && p[i].x<tmp.x)
            {
                tmp.x=p[i].x;
                tmp.y=p[i].y;
                pos=i;
            }
        }


        swap(p[0], p[pos]);
    /*    tmp=p[0];
        p[0]=p[pos];
        p[pos]=tmp;*/


        qsort(&p[1], n-1, sizeof(p[0]), cmp);
        p[n]=p[0];
        create_convex(n);
        double len=0.0;
        for (i=1; i<=top; i++)
        {
            len+=dist(result[i-1], result[i]);
        }
        printf("%.2lf\n", len);


    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值