[USACO5.1.1]Fencing the Cows圈奶牛 求二维凸包板题
计算几何求凸包模板,没什么好说的。
luogu2742
农夫约翰想要建造一个围栏用来围住他的奶牛,可是他资金匮乏。他建造的围栏必须包括他的奶牛喜欢吃草的所有地点。对于给出的这些地点的坐标,计算最短的能够围住这些点的围栏的长度。
n 1e5
要么提出最左边点之后作为极坐标原点按照极坐标排序,要么按照x从小到大排序然后左扫一遍右扫一遍。
我们主要是判断一个折线的拐向是向外拐还是向内拐,这个可以用叉积加右手定则搞定逆时针旋转是在[0,pi](>0)还是[pi,2*pi](<0)。
#include<cstdio> #include<algorithm> #include<iostream> #include<cmath> using namespace std; const int maxn = 3e5+5; typedef double db; const db eps = 1e-8; int n; struct node{ db x,y; }z[maxn]; node operator-(node aa,node bb) { return (node){aa.x-bb.x,aa.y-bb.y}; } node operator+(node aa,node bb) { return (node){aa.x+bb.x,aa.y+bb.y}; } node operator*(node aa,node bb) { return (node){aa.x*bb.x,aa.y*bb.y}; } db operator^(node aa,node bb) { return aa.x*bb.y - aa.y*bb.x; } db operator/(node aa,node bb) { return sqrt( (aa.x-bb.x)*(aa.x-bb.x) + (aa.y-bb.y)*(aa.y-bb.y) ); } int qe[maxn];int ql,qr; bool cmpx(node aa,node bb) { return aa.x < bb.x; } db chaji(int a,int b,int c) { //oa cha ob node oa = z[b]-z[a]; node ob = z[c]-z[a]; return oa^ob; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%lf%lf",&z[i].x,&z[i].y); } sort(z+1,z+1+n,cmpx); int t = 0 , tmp; for(int i=1;i<=n;i++) { while(t>=2&&chaji(qe[t-1],qe[t],i)<0) t--; qe[++t] = i; } for(int i=n-1;i>=1;i--) { while(t>=2&&chaji(qe[t-1],qe[t],i)<0) t--; qe[++t] = i; } db ans = 0; for(int i=1;i<t;i++) { ans += ( z[qe[i]]/(z[qe[i+1]]) ); } printf("%.2f",ans); }