【凸包构造】LightOJ 1203 Guarding Bananas

【凸包构造】LightOJ 1203 Guarding Bananas

题目链接:LightOJ 1203 Guarding Bananas

题目大意

构造凸包,求凸包夹角的最小值

这里写图片描述

笔者的第一道凸包题目,发现Kuangbin的计算几何模板的一个最大缺陷:结构体太长,大空间开不下QAQ

凸包,我的理解是包含已知点集的最小凸集,二维凸包自然可以理解为包含所有点的最小凸多边形。

现在代码的逼格越来越高了~(≧▽≦)/~啦啦啦!

这里写图片描述

说一下思路

  • ①Graham’s Scan法构建凸包,时间复杂度O(nlogn)
  • ②遍历凸包中所有顶点,利用余弦定理求出所有夹角并取出其中的最小值

参考代码

/*==================================================*\
| Graham求凸包 O(N * logN)
| CALL: nr = graham(pnt, int n, res); res[]为凸包点集;
\*==================================================*/
/*Author:Hacker_vision*/
#include<bits/stdc++.h>
#define eps 1e-8
using namespace  std;

const int _max = 1e5 + 10;
const double PI = acos(-1);
int n;

struct point{double x,y;}p[_max],res[_max];

bool mult(point sp,point ep,point op){
  return (sp.x - op.x) * (ep.y - op.y)
       >= (ep.x - op.x) * (sp.y - op.y);
}

bool operator < (const point &l, const point &r){
   return l.y < r.y ||(l.y == r.y && l.x < r.x);
}

int graham(point pnt[],int n, point res[]){//构造凸包
  int i,len ,k = 0,top = 1;
  sort(pnt,pnt+n);
  if(n == 0)return 0; res[0] = pnt[0];
  if(n == 1)return 1; res[1] = pnt[1];
  if(n == 2)return 2; res[2] = pnt[2];
  for(int i =2; i < n; ++ i){
    while(top && mult(pnt[i],res[top],res[top-1]))
        top--;
    res[++top] = pnt[i];
  }
  len = top; res[++top] = pnt[n - 2];
  for(i = n - 3; i >= 0; -- i){
    while(top!=len && mult(pnt[i],res[top],res[top-1]))
        top--;
    res[++top] = pnt[i];
  }
  return top;//返回凸包中点的个数
}

double len(point A,point B){//返回向量AB的模
  return hypot(A.x-B.x,A.y-B.y);
}

double dot(point A,point B,point C){//点乘
  return (C.x-A.x)*(B.x-A.x)+(C.y-A.y)*(B.y-A.y);
}

double get(point A,point B,point C){//余弦定理
  return acos(dot(A,B,C)/len(A,B)/len(A,C));
}

double minangle(){//遍历凸包所有点,余弦定理求角
  if(n < 3) return 0;
  double ans = 2 * PI;
  res[n] = res[0];res[n+1] = res[1];
  for(int i = 1; i<= n; ++ i){
    ans = min(ans,get(res[i],res[i+1],res[i-1]));
  }
  return ans/PI*180;
}

int main(){
  #ifndef ONLINE_JUDGE
  freopen("input.txt","r",stdin);
  #endif // ONLINE_JUDGE
  int T;cin>>T;int cnt=1;
  while(T--){
    scanf("%d",&n);
    for(int i = 0; i < n; ++ i){
        scanf("%lf%lf",&p[i].x,&p[i].y);
    }
    n = graham(p,n,res);//构造凸包
    printf("Case %d: ",cnt++);
    printf("%.7f\n",minangle());
  }
  return 0;
}
  • 加粗 Ctrl + B
  • 斜体 Ctrl + I
  • 引用 Ctrl + Q
  • 插入链接 Ctrl + L
  • 插入代码 Ctrl + K
  • 插入图片 Ctrl + G
  • 提升标题 Ctrl + H
  • 有序列表 Ctrl + O
  • 无序列表 Ctrl + U
  • 横线 Ctrl + R
  • 撤销 Ctrl + Z
  • 重做 Ctrl + Y
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值