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

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

题目描述

农夫约翰想要建造一个围栏用来围住他的奶牛,可是他资金匮乏。他建造的围栏必须包括他的奶牛喜欢吃草的所有地点。对于给出的这些地点的坐标,计算最短的能够围住这些点的围栏的长度。

输入输出格式


输入格式

输入数据的第一行包括一个整数 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

说明


题目翻译来自NOCOW。

USACO Training Section 5.1

分析


没啥分析,典型的板子题,多打。

我的代码

#include<bits/stdc++.h>
using namespace std;

int n;
struct node{
	double x,y;
}a[10010],s[10010];
int mi=0;
double ans;
double ju(node aa,node bb,node cc){
	return ((aa.x-cc.x)*(aa.x-cc.x)+(aa.y-cc.y)*(aa.y-cc.y))-((bb.x-cc.x)*(bb.x-cc.x)+(bb.y-cc.y)*(bb.y-cc.y));
}
double jiao(node aa,node bb,node cc){
	return (aa.x-cc.x)*(bb.y-cc.y)-(bb.x-cc.x)*(aa.y-cc.y);
}
bool cmp(node aa,node bb){
	if(jiao(aa,bb,a[0])>0)
		return 1;
	if(jiao(aa,bb,a[0])==0&&ju(aa,bb,a[0])<=0)
		return 1;
	return 0;
}

int main(){
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%lf%lf",&a[i].x,&a[i].y); //cin>>a[i].x>>a[i].y;
		if(a[i].y<a[mi].y||(a[i].y==a[mi].y&&a[i].x<a[mi].x))
			mi=i;
	}
	node lin=a[mi];
	a[mi]=a[0];
	a[0]=lin;
	sort(a+1,a+n,cmp);
	s[0]=a[0];
	s[1]=a[1];
	int top=1;
	for(int i=2;i<n;i++){
		while(top>1&&jiao(s[top-1],a[i],s[top])>0)
			top--;
		s[++top]=a[i];
	}
	for(int i=1;i<=top;i++)
		ans+=sqrt((s[i].x-s[i-1].x)*(s[i].x-s[i-1].x)+(s[i].y-s[i-1].y)*(s[i].y-s[i-1].y));
	ans+=sqrt((s[top].x-s[0].x)*(s[top].x-s[0].x)+(s[top].y-s[0].y)*(s[top].y-s[0].y));
	printf("%.2f",ans);
	return 0;
}

太丑的话见谅见谅。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值