LightOJ 1203--Guarding Bananas(二维凸包+内角计算)
| 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 trees. The monkey didn't want to lose any of the bananas. So, he wanted to find a banana such that he can eat that and he can also look after the other bananas. As he was lazy, he didn't want to move his eyes too wide. So, you have to help him finding the banana from where he can look after all the bananas but the degree of rotating his eyes is as small as possible. You can assume that the position of the bananas can be modeled as 2D points.

Here a banana is shown, from where the monkey can look after all the bananas with minimum eye rotation.
Input
Input starts with an integer T (≤ 13), denoting the number of test cases.
Each case starts with a line containing an integer n (1 ≤ n ≤ 105) denoting the number of bananas. Each of the next n lines contains two integers x y (-109 ≤ x, y ≤ 109) denoting the co-ordinate of a banana. There can me more than one bananas in the same co-ordinate.
Output
For each case, print the case number and the minimum angle in degrees. Errors less than 10-6 will be ignored.
Sample Input |
Output for Sample Input |
|
2 1 4 4 4 0 0 10 0 10 10 2 1 |
Case 1: 0 Case 2: 45.0000000 |
Note
Dataset is huge. Use faster I/O methods.
- 题意:在所有给定的香蕉中找到一个香蕉,使得从这个香蕉看向其他香蕉的角度尽可能小的同时看到的香蕉数目尽可能多。
- 由于香蕉可以化为半径忽略不计的二维平面上的点,所以可以想到,站在这些点的凸包的顶点处看过去的角度小并且看到的点更多,否则,总可以向这些定顶点处移动,使得看到的点更多或者角度更小。
- 所以这道题就是求其凸包,然后找到里面最小的那个内角。
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1e5 + ;
const double pi = acos(-1.0);
const double eps = 1e-;
int sgn(double x) {
if (fabs(x) < eps)return ;
if (x < )return -;
else return ;
}
typedef struct point {
double x, y;
point() { }
point(double a, double b) {
x = a;
y = b;
}
point operator -(const point &b) const {
return point(x - b.x, y - b.y);
}
double operator *(const point &b)const {
return x*b.x + y*b.y;
}
double operator ^(const point &b)const { //叉乘
return x*b.y - y*b.x;
}
bool operator <(point b)const {
return sgn(x - b.x) == ? sgn(y - b.y)< : x<b.x;
}
//返回pa,pb的夹角,该点看a,b的夹角,弧度制
//弧度=度×π/180°
//度=弧度×180°/π
double rad(point a, point b) {
point p = *this;
return fabs(atan2(fabs((a - p) ^ (b - p)), (a - p)*(b - p)));
}
}point;
point p[maxn];
int n = , res[maxn];
int top;//top模拟栈顶
bool multi(point p1, point p2, point p0) { //判断p1p0和p2p0的关系,<0,p1p0在p2p0的逆时针方向,>0,p1p0在p2p0的顺时针方向
return (p1.x - p0.x)*(p2.y - p0.y) >= (p2.x - p0.x)*(p1.y - p0.y);
}
double Graham() {
int i, len;//top模拟栈顶
sort(p, p + n);
top = ;
//少于3个点也就没有办法形成凸包
if (n == )return ; res[] = ;
if (n == )return ; res[] = ;
if (n == )return ; res[] = ;
for (i = ; i < n; i++) {
while (top&&multi(p[i], p[res[top]], p[res[top - ]])) //如果当前这个点和栈顶两个点构成折线右拐了,就回溯到上一个点
top--; //弹出栈顶
res[++top] = i; //否则将这个点入栈
}
len = top;
res[++top] = n - ;
for (i = n - ; i >= ; i--) {
while (top != len&&multi(p[i], p[res[top]], p[res[top - ]]))
top--;
res[++top] = i;
}
double ans =0x3f3f3f;
res[top] = res[],res[top + ] = res[];
for (int i = ; i <= top; i++) {
ans = min(ans, p[res[i]].rad(p[res[i + ]], p[res[i - ]]));
}
return ans / pi * ;
}
inline int read()
{
int x = , f = ; char ch = getchar();
while (ch<'' || ch>'') { if (ch == '-')f = -; ch = getchar(); }
while (ch >= ''&&ch <= '') { x = x * + ch - ''; ch = getchar(); }
return x*f;
}
int main(void) {
int t;
t = read();
for (int cnt = ; cnt <= t; cnt++) {
cin >> n;
for (int i = ; i < n; i++) {
p[i].x = read();
p[i].y = read();
}
printf("Case %d: ", cnt);
printf("%.7lf\n", Graham());
}
return ;
}
LightOJ 1203--Guarding Bananas(二维凸包+内角计算)的更多相关文章
- LightOJ 1203 Guarding Bananas (凸包最小顶角)
题目链接:LightOJ 1203 Problem Description Once there was a lazy monkey in a forest. But he loved banana ...
- 计算几何 二维凸包问题 Andrew算法
凸包:把给定点包围在内部的.面积最小的凸多边形. Andrew算法是Graham算法的变种,速度更快稳定性也更好. 首先把全部点排序.依照第一keywordx第二keywordy从小到大排序,删除反复 ...
- 使用Graham扫描法求二维凸包的一个程序
#include <iostream> #include <cstring> #include <cstdlib> #include <cmath> # ...
- luogu P2742 【模板】二维凸包 / [USACO5.1]圈奶牛Fencing the Cows
题解: 二维凸包裸题 按照x坐标为第一关键字,y坐标为第二关键字排序 然后相邻判断叉积用单调队列搞过去 正反都做一次就好了 代码: #include <bits/stdc++.h> usi ...
- Luogu P2742 模板-二维凸包
Luogu P2742 模板-二维凸包 之前写的实在是太蠢了.于是重新写了一个. 用 \(Graham\) 算法求凸包. 注意两个向量 \(a\times b>0\) 的意义是 \(b\) 在 ...
- 【洛谷 P2742】【模板】二维凸包
题目链接 二维凸包板子..有时间会补总结的. #include <cstdio> #include <cmath> #include <algorithm> usi ...
- poj 2079 Triangle (二维凸包旋转卡壳)
Triangle Time Limit: 3000MS Memory Limit: 30000KB 64bit IO Format: %I64d & %I64u Submit Stat ...
- poj 2187 Beauty Contest(二维凸包旋转卡壳)
D - Beauty Contest Time Limit:3000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u ...
- UVA 10652 Board Wrapping(二维凸包)
传送门 刘汝佳<算法竞赛入门经典>P272例题6包装木板 题意:有n块矩形木板,你的任务是用一个面积尽量小的凸多边形把它们抱起来,并计算出木板占整个包装面积的百分比. 输入:t组数据,每组 ...
随机推荐
- js-滚动到指定位置导航栏固定顶部
最近整理一下之前做的一个项目,把滚动条动态固定顶部的代码整理出来和大家分享,上代码 <!DOCTYPE html> <html> <head> <meta c ...
- Ubuntu 中QT 用sogou拼音 安装
1.下载搜狗输入法的安装包 下载地址为:http://pinyin.sogou.com/linux/ ,如下图,要选择与自己系统位数一致的安装包,我的系统是64位,所以我下载64位的安装包 2.按键C ...
- 【PHP系列】框架的抉择
缘起 在PHP开发中,选择合适的框架有助于加快软件开发,节约宝贵的项目时间,让开发者专注于功能的实现上.框架的问题是需要很多的投入,选择框架时,我们更看重这个框架的未来,存在多年的大型框架必须要有好的 ...
- 使用C++11实现完美资源管理
1.资源管理包括内存管理.文件句柄等等需要进行打开(申请).关闭(释放)操作的过程 2.VS2010使用的C++规范,严格说来不是C++11,而是C++0x,但是一脉相承的 一:管理数组 相较于aut ...
- Math类中常用方法
public static int abs(int a) , public static long abs(long a), public static float abs(float a), pu ...
- Thread.Join()的详解
什么是进程?当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源.而一个进程又是由多个线程所组成的. 什么是线程?线程是程序中的一个执行流,每个线程都有自己的专有寄 ...
- vagrant 安装虚拟机
目录 搭建属于你的环境 安装virtualbox 安装 vagrant vagrant 添加系统镜像box 新建虚拟机 相关配置 ==遇到问题== [TOC] 搭建属于你的环境 安装环境有时也是头疼的 ...
- MARKS:路由器桥接
仅供参考…… 测试使用环境:Tplink & Tenda渣渣路由器.其他环境或不同. 设置注意事项:副路由器网段设置和主路由一致.主路由不需要开启WDS.副路由器开启WDS(连接ok,状态即显 ...
- QT信号和槽在哪个线程执行问题
时隔四个月后的第一篇,换了个公司可以登录的博客,记录一些学习内容吧 这是看到别人写的比较好的一篇,排版有点乱 QThread的使用方法 起源 昨天不小心看到Qt开发人员( Bradley T.Hugh ...
- 快速搭建一个SSM框架demo
我之所以写一个快速搭建的demo,主要想做一些容器的demo,所以为了方便大家,所以一切从简,简单的3层架构 先用mysql的ddl,后期不上oracle的ddl ; -- ------------- ...