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

题解:

二维凸包裸题

按照x坐标为第一关键字,y坐标为第二关键字排序

然后相邻判断叉积用单调队列搞过去

正反都做一次就好了

代码:

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for (int i=h;i<=t;++i)
#define dep(i,t,h) for (int i=t;i>=h;--i) 
const int N=2e4;
const double eps=1e-10;
struct Point{
  double x,y,r;
  Point(){};
  Point(double x1,double y1)
  {
    x=x1; y=y1;
  }
  IL void jsr()
  {
    r=atan2(y,x);
  }
  Point operator -(const Point b) const
  {
    return Point(x-b.x,y-b.y);
  }
  double operator ^(const Point b) const
  {
    return x*b.y-y*b.x;
  }
}p[N],q[N];
IL int dcmp(double x)
{
  if (x<-eps) return(-1); else
  if (x>eps) return(1); else return(0);
}
bool cmp(Point x,Point y)
{
  return dcmp(x.x-y.x)<0||(dcmp(x.x-y.x)==0&&dcmp(x.y-y.y)==-1);
}
int n,t;
void push(Point now)
{
  while (dcmp((now-q[t])^(q[t]-q[t-1]))>0) --t;
  q[++t]=now;
}
IL double dis(Point x,Point y)
{
  return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));
}
int main()
{
  ios::sync_with_stdio(false);
  cin>>n;
  rep(i,1,n)
  {
    double x,y;
    cin>>x>>y;
    p[i]=Point(x,y);
    p[i].jsr();
  }
  sort(p+1,p+n+1,cmp);
  t=1;
  q[0]=q[t]=p[1];
  rep(i,2,n) push(p[i]);
  dep(i,n-1,1) push(p[i]);
  double ans=0;
  rep(i,1,t-1) ans+=dis(q[i],q[i+1]);
  printf("%.2lf",ans);
  return 0;
}

 

posted @ 2018-11-22 21:56  尹吴潇  阅读(197)  评论(0编辑  收藏  举报