P2742 【模板】二维凸包 / [USACO5.1]圈奶牛Fencing the Cows](https://www.luogu.com.cn/problem/P2742)
题目描述
农夫约翰想要建造一个围栏用来围住他的奶牛,可是他资金匮乏。他建造的围栏必须包括他的奶牛喜欢吃草的所有地点。对于给出的这些地点的坐标,计算最短的能够围住这些点的围栏的长度。
输入格式
输入数据的第一行包括一个整数 N。N(0 <= N <= 10,000)表示农夫约翰想要围住的放牧点的数目。接下来 N 行,每行由两个实数组成,Xi 和 Yi,对应平面上的放牧点坐标(-1,000,000 <= Xi,Yi <= 1,000,000)。数字用小数表示。
输出格式
输出必须包括一个实数,表示必须的围栏的长度。答案保留两位小数。
输入输出样例
输入 #1
4
4 8
4 12
5 9.3
7 8
输出 #1
12.00
#include<stdio.h>
#include<cmath>
#include<algorithm>
using namespace std;
struct node{
double x,y;
}p[10005],s[10005];
double check(node a1,node a2,node b1,node b2){// 求叉积
return (a2.x-a1.x)*(b2.y-b1.y)-(b2.x-b1.x)*(a2.y-a1.y);
}
double d(node a,node b){//两点距离
return sqrt((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y));
}
bool cmp(node x,node y){
double temp=check(s[1],x,s[1],y);
if(temp>0)
return 1;
if(temp==0&&d(s[0],x)<d(s[0],y))
return 1;
return 0;
}
int main()
{
int n,i,j;
double mid;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%lf %lf",&s[i].x,&s[i].y);
if(i!=1&&s[1].y>s[i].y){//求坐标最低的一点
swap(s[1].x,s[i].x);
swap(s[1].y,s[i].y);
}
}
s[0].x=s[0].y=0;
sort(s+2,s+1+n,cmp);
for(int i=1;i<=n;i++)
printf("%lf %lf\n",s[i].x,s[i].y);
p[1]=s[1];
int top=1;
for(i=2;i<=n;i++){
while(top>1&&check(p[top-1],p[top],p[top],s[i])<=0)//更新
top--;
p[++top]=s[i];
}
p[top+1]=s[1];
double ans=0;
for(i=1;i<=top;i++)
ans+=d(p[i],p[i+1]);
printf("%.2lf\n",ans);
return 0;
}
来源:CSDN
作者:海马有力量
链接:https://blog.csdn.net/qq_20087731/article/details/104062779