P2742 【模板】二维凸包 / [USACO5.1]圈奶牛Fencing the Cows

本秂侑毒 提交于 2020-01-22 03:00:15

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;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!