ZOJ - 1453 Surround the Trees(凸包模板)

题目链接https://vjudge.net/contest/368988#problem/A
There are a lot of trees in an area. A peasant wants to buy a rope to surround all these trees. So at first he must know the minimal required length of the rope. However, he does not know how to calculate it. Can you help him?
The diameter and length of the trees are omitted, which means a tree can be seen as a point. The thickness of the rope is also omitted which means a rope can be seen as a line.
在这里插入图片描述
There are no more than 100 trees.
Input
The input contains one or more data sets. At first line of each input data set is number of trees in this data set, it is followed by series of coordinates of the trees. Each coordinate is a positive integer pair, and each integer is less than 32767. Each pair is separated by blank.
Zero at line for number of trees terminates the input for your program.

Output
The minimal length of the rope. The precision should be 10^-2.
Sample Input

 9 
 12 7 
 24 9 
 30 5 
 41 9 
 80 7 
 50 87 
 22 9 
 45 1 
 50 7 
 0  

Sample Output

243.06

翻译
给定n个点的坐标,求把这n个点围起来所需要的的最小长度。

知识点

凸包的概念
包围原点集的最小凸多边形的顶点组成的集合,称为原点集的凸包。
(这些顶点的特点:不在任意三个点组成的三角形内部)

如何求凸包?–Graham扫描算法

  1. 点集按x坐标->y坐标的字典序升序排序(排序后的第一个和最后一个必然是凸包上的顶点)
  2. 分为上下两条链求解。
  3. 利用叉积的性质,遍历每一个点,若有凹进去的部分则消去。

在这里插入图片描述

代码:

#include<cstdio>
#include<cstring>
#include<math.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
const int N=1e2+10;
struct node
{
    int x,y;
} p[N],st[N];
int n,top;
int cmp(node t1,node t2)///字典序比较
{
    if(t1.x!=t2.x)
        return t1.x<t2.x;
    return t1.y<t2.y;
}
int solve(node a,node b,node c)///两个向量的叉积
{
    return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
void graham()
{
    ///遍历上下链把符合情况的点存到栈中,最后可以for循环遍历计算周长
    top=0;
    for(int i=0; i<n; i++)///下侧链
    {
        while(top>1&&solve(st[top-2],st[top-1],p[i])<=0)///叉积小于0,说明新的点i,能让栈的首元素处于内部,可以删去
            top--;
        st[top++]=p[i];
    }
    for(int i=n-2,t=top; i>=0; i--)///上侧链
    {
        while(top>t&&solve(st[top-2],st[top-1],p[i])<=0)
            top--;
        st[top++]=p[i];
    }
}
double squary(node t1,node t2)
{
    return sqrt((t1.x-t2.x+0.0)*(t1.x-t2.x)*1.0+(0.0+t1.y-t2.y)*1.0*(t1.y-t2.y));
}
int main()
{
    while(~scanf("%d",&n)&&n)
    {
        for(int i=0; i<n; i++)
            scanf("%d%d",&p[i].x,&p[i].y);
        sort(p,p+n,cmp);
        graham();
        double sum=0;
        for(int i=1; i<top; i++)
            sum+=squary(st[i],st[i-1]);
        sum+=squary(st[0],st[top-1]);
        printf("%.2lf\n",sum);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zaiyang遇见

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值