圈奶牛--二维凸包
1.学习文章(凸包问题)P2742 [USACO5.1] 圈奶牛Fencing the Cows /【模板】二维凸包_c语言凸包问题-CSDN博客2.题目+题解第一篇理解
https://www.luogu.com.cn/problem/P2742
#include<bits/stdc++.h>
using namespace std;
#define N 100011
typedef long long ll;
typedef pair<ll,int> pii;
int n;
struct Point {double x,y;
} an[N],a[N];
int k;
double Cross(double ax,double ay,double bx,double by)///叉积,就是向量a,b的斜率比较
///cross>1即ka<kb
///符合从最左下角到下凸包的前进方向
{return ax*by-ay*bx; //A->B左转为正
}
bool cmp(struct Point a,struct Point b) {if(a.x==b.x) return a.y<b.y;else return a.x<b.x;
}
int sgn(double x) {if(fabs(x) <= 1e-6) return 0;///忽略精度损失带来的影响 return (x>=0 ? 1 : -1);
}
void andre() {an[k++] = a[0];///第一个点就是左下角for(int i=1; i<n; i++) {while (k > 1 && sgn(Cross(an[k-1].x-an[k-2].x , an[k-1].y-an[k-2].y,a[i].x-an[k-1].x,a[i].y-an[k-1].y)) <= 0)///不符合条件就删去这个点,同时要保留第一个点{k--;}an[k++] = a[i];///}int t = k;///第k-1个点是a[n-1],然后逆序遍历,找上凸包for(int i=n-2; i>=0; i--) {Point aa,b;aa.x=(double)(an[k-1].x-an[k-2].x),aa.y=(double)(an[k-1].y-an[k-2].y);b.x=(double)(a[i].x-an[k-1].x),b.y=(double)(a[i].y-an[k-1].y);while (k > t && sgn(Cross(an[k-1].x-an[k-2].x , an[k-1].y-an[k-2].y,a[i].x-an[k-1].x,a[i].y-an[k-1].y)) <= 0)k--;///保留下凸包的点an[k++] = a[i];}if(n > 1) k--;
}
double d(Point p1,Point p2) { //两点间距离。。。return sqrt((p2.y-p1.y)*(p2.y-p1.y)+(p2.x-p1.x)*(p2.x-p1.x));
}
int main() {cin>>n;for(int i=0; i<n; i++) cin>>a[i].x>>a[i].y;sort(a,a+n,cmp);///先排序,x从小到大,x相同的情况y从小到大if(n<3) cout<<-1;else {andre();double s=0;for(int i=0; i<k; i++) {s+=d(an[i],an[i+1]);}s+=d(an[0],an[k]);printf("%.02lf",s);}return 0;
}