ACWING1401. 围住奶牛
ACWING1401. 围住奶牛
描述
农夫约翰想要建造一个围栏来围住奶牛。
构建这个围栏时,必须将若干个奶牛们喜爱的地点都包含在围栏内。
现在给定这些地点的具体坐标,请你求出将这些地点都包含在内的围栏的最短长度是多少。
注意:围栏边上的点也算处于围栏内部。
思路
凸包模板题。
代码
#include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<double,double> pdd;
int n;
const int N=10010;
pdd q[N];
int stk[N];
bool used[N];
const double EPS=1e-8;
double get_dist(pdd a,pdd b){
double dx=a.x-b.x;
double dy=a.y-b.y;
return sqrt(dx*dx+dy*dy);
}
pdd operator-(pdd a,pdd b){
return {a.x-b.x,a.y-b.y};
}
double cross(pdd a,pdd b){
return a.x*b.y - a.y*b.x;
}
double area(pdd a,pdd b,pdd c){
return cross(b-a,c-a);
}
int sign(double x){
if(fabs(x)<EPS) return 0;
if(x<0) return -1;
return 1;
}
double andrew(){
sort(q,q+n);
int top=0;
for(int i=0;i<n;i++){
while(top>=2 && sign(area(q[stk[top-1]],q[stk[top]],q[i]))<=0){
if(sign(area(q[stk[top-1]],q[stk[top]],q[i]))<0)
used[stk[top--]]=false;
else top--;
}
stk[++top]=i;
used[i]=true;
}
used[0]=false;
for(int i=n-1;i>=0;i--){
if(used[i]) continue;
while(top>=2 && sign(area(q[stk[top-1]],q[stk[top]],q[i]))<=0)
top--;
stk[++top]=i;
}
double res=0;
for(int i=2;i<=top;i++){
res+=get_dist(q[stk[i-1]],q[stk[i]]);
}
return res;
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%lf%lf",&q[i].x,&q[i].y);
double res=andrew();
printf("%.2f\n",res);
return 0;
}