洛谷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;
}
太丑的话见谅见谅。