bzoj 1670 Building the Moat护城河的挖掘 —— 凸包

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1670

单调栈维护凸包即可,用叉积判断;

维护上凸壳,然后把所有点的纵坐标翻转再求上凸壳即可,要注意排序规则略有变化。

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef double db;
int const xn=5005;
db const eps=1e-8;
int n,top,mx;
db ans;
struct N{
  db x,y;
  N(db x=0,db y=0):x(x),y(y) {}
  bool operator < (const N &b) const
  {return x<b.x||(x==b.x&&y<b.y);}
}p[xn],sta[xn];
bool cmp(N a,N b){return a.x<b.x||(a.x==b.x&&a.y>b.y);}
N operator - (const N &a,const N &b){return N(a.x-b.x,a.y-b.y);}
int rd()
{
  int ret=0,f=1; char ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
  while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
  return f?ret:-ret;
}
int maxx(int x,int y){return x<y?y:x;}
db sqr(db x){return x*x;}
db cross(N a,N b){return a.x*b.y-a.y*b.x;}
db len(N a){return sqrt(sqr(a.x)+sqr(a.y));}
db dis(N a,N b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}
int dmp(db x){if(fabs(x)<=eps)return 0; return x>eps?1:-1;}
void work()
{
  top=0;
  for(int i=1;i<=n;i++)
    {
      while(top>1&&dmp(cross(sta[top]-sta[top-1],p[i]-sta[top]))>=0)top--;
      sta[++top]=p[i];
    }
  while(top>1)ans+=len(sta[top]-sta[top-1]),top--;
}
int main()
{
  n=rd(); mx=0;
  for(int i=1;i<=n;i++)p[i].x=rd(),p[i].y=rd(),mx=maxx(mx,p[i].y);
  sort(p+1,p+n+1);
  work();
  for(int i=1;i<=n;i++)p[i].y=mx-p[i].y+1;
  sort(p+1,p+n+1,cmp);//
  work();
  printf("%.2f\n",ans);
  return 0;
}

 

posted @ 2018-12-19 16:49  Zinn  阅读(178)  评论(0编辑  收藏  举报