题目链接: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扫描算法
- 点集按x坐标->y坐标的字典序升序排序(排序后的第一个和最后一个必然是凸包上的顶点)
- 分为上下两条链求解。
- 利用叉积的性质,遍历每一个点,若有凹进去的部分则消去。
代码:
#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;
}