【简单凸包】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

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 01:14:48

【简单凸包】LightOJ 1203 Guarding Bananas的相关文章

LightOj1203 - Guarding Bananas(凸包求多边形中的最小角)

题目链接:http://lightoj.com/volume_showproblem.php?problem=1203 题意:给你一个点集,求凸包中最小的角:模板题,但是刚开始的时候模板带错了,错的我都想吐了: #include <stdio.h> #include <algorithm> #include <cstring> #include <cmath> using namespace std; #define met(a, b) memset(a,

UVa 10652 (简单凸包) Board Wrapping

题意: 有n块互不重叠的矩形木板,用尽量小的凸多边形将它们包起来,并输出并输出木板总面积占凸多边形面积的百分比. 分析: 几乎是凸包和多边形面积的裸题. 注意:最后输出的百分号前面有个空格,第一次交PE了. 用printf打印%,可以连续打印两个%%,printf("%%\n");   这个冷知识记得以前学过,不过不用也就忘了. 学习一下vector容器中去重的小技巧. sort(p.begin(), p.end()); p.erase(unique(p.begin(), p.end(

LightOJ 1203--Guarding Bananas(二维凸包+内角计算)

1203 - Guarding Bananas    PDF (English) Statistics Forum Time Limit: 3 second(s) Memory Limit: 32 MB Once there was a lazy monkey in a forest. But he loved banana too much. One day there was a storm in the jungle and all the bananas fell from the tr

【BZOJ】1027: [JSOI2007]合金(凸包+floyd)

http://www.lydsy.com/JudgeOnline/problem.php?id=1027 没special judge wa了一发好蛋疼... 首先这题大概和黑书上的差不多...由于知道任意两种材料就能得到第三种材料的含量,所以可以忽略第三种含量... 首先来看,如果有两种材料,那么能合成的材料一定在这个线段上,证明很简单... 假设材料A和B,要合成材料C,将他们材料的含量放到二维坐标系上(x轴为材料1,y轴为材料2) 假设用了a的A,则用了1-a的B,有 $$\begin{a

hdu 1348 Wall (凸包)

Wall Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3139    Accepted Submission(s): 888 Problem Description Once upon a time there was a greedy King who ordered his chief Architect to build a w

凸包---(简单概念)

这里先介绍点概念(一般是点集覆盖问题)输入各个点的坐标 1. 将各点排序(必须的) ,为保证形成圈,把 P0 在次放在点表的尾 部: 2. 准备堆栈:建立堆栈 S,栈指针设为t,将0.1.2 三个点压入堆栈 S: 3. 对于下一个点 i 只要 S[t-1].S[t].i不做左转 就反复退栈: 将 i压入堆栈 S 4.堆栈中的点即为所求凸包: 其核心用 C 语言表示,仅仅是下面一段: t=-1; s[++t]=0; s[++t]=1; s[++t]=2; for (i=3;i<n;i++) { w

lightoj 1245 Harmonic Number (II)(简单数论)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1245 题意:求f(n)=n/1+n/2.....n/n,其中n/i保留整数 显然一眼看不出什么规律.而且n有2e31直接暴力肯定要出事情 但是f=n/x这个函数很好关于y = x 对称对称点刚好是sqrt(n) 于是就简单了直接求sum+n/i (i*i<n && i >=1) 然后乘以2,再减去i*i即可. 这个i*i表示的是什么呢,由于对称上半部份的值完

URAL 1203 Scientific Conference 简单dp 难度:0

http://acm.timus.ru/problem.aspx?space=1&num=1203 按照结束时间为主,开始时间为辅排序,那么对于任意结束时间t,在此之前结束的任务都已经被处理,从这个时间开始的任务都正要被处理, 因为t<=3e5,可以用简单dp解决 #include <cstdio> #include <algorithm> using namespace std; const int maxn=1e5+5; int n; typedef pair&l

LightOJ 1012 简单bfs,水

1.LightOJ 1012  Guilty Prince  简单bfs 2.总结:水 题意:迷宫,求有多少位置可去 #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #define F(i,a,b) for (int i=a;i<=b;i++) using names