【题解】「UVA11626」Convex Hull
凸包模板题。
之前写过拿 Graham 算法求凸包的,为了不重复/多学点知识,那这次拿 Andrew 算法求凸包吧qaq
*此文章所有图片均为作者手画。
Andrew 算法
假设我们有这些点:

首先把所有点以横坐标为第一关键字,纵坐标为第二关键字排序。

相对于 Graham 算法来说,Andrew 算法排序更简单,按 \(x, y\) 坐标排序,时间复杂度也更低(一般的坐标系中排序方法)。
首先将 \(p_1\) 入栈。
然后也将 \(p_2\) 入栈,\(p_2\) 可能在,也可能不在,等着之后判断。

随后,发现 \(p_3\) 偏右,所以我们将 \(p_2\) 出栈。

发现 \(p_4\) 依然偏右,\(p_3\) 出栈,\(p_4\) 入栈。

\(p_5\) 向右,\(p_4\) 出栈,\(p_5\) 入栈。

\(p_6\) 向左,入栈。

\(p_7\) 向右,\(p_6\) 出栈,\(p_7\) 入栈。

\(p_8\) 向右,\(p_7\) 出栈,继续检查发现相对于 \(p_5\) \(p_8\) 仍然向右,\(p_5\) 出栈,\(p_8\) 入栈。

此时,我们发现,凸包明明还空一半就到头了???
然而这是意料之中,我们这种算法必然会只算出一半的凸包。
所以我们需要再从排序末尾的点(也就是 \(p_8\))出发,按照一模一样的方式再算一遍就行了。
当然如果我们走过的点就不许要再走了(除了 \(p_1\))
从 \(p_8\) 到 \(p_7\),向左,\(p_7\) 入栈。

\(p_6\) 向右,\(p_7\) 出栈,\(p_6\) 入栈。

\(p_5\) 向左,入栈。

\(p_4\) 向左,入栈。

\(p_3\) 向右,\(p_4\) 出栈,对于 \(p_5\) \(p_3\) 依然向右,\(p_5\) 出栈,\(p_3\) 入栈。

\(p_2\) 向右,\(p_3\) 出栈,\(p_2\) 入栈。

最后将 \(p_2\) 和 \(p_1\) 连起来。

至此,我们的 Andrew 算法就完成了!
扫描的时间复杂度:\(O(n)\)(已过滤常数)
排序时间复杂度:\(O(n \log n)\)
总时间复杂度:\(O(n \log n)\)
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#define line cout << endl
using namespace std;
const int NR = 1e5 + 5;
const double eps = 1e-7;
int n;
struct point {
double x, y;
point () {}
point (double a, double b) : x (a), y (b) {}
bool operator < (const point &b) const {
if (x < b.x) return 1;
if (x > b.x) return 0;
return y < b.y;
}
point operator - (const point &b) {
return point (x - b.x, y - b.y);
}
};
point p[NR], sp[NR];
int cmp (double x) {
if (fabs (x) < eps) return 0;
return x > 0 ? 1 : -1;
}
double dis (point a, point b) {
return sqrt ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
double cp (point a, point b) {
return a.x * b.y - a.y * b.x;
}
int Andrew () {
sort (p + 1, p + 1 + n);
int len = 0;
for (int i = 1; i <= n; i++) {
while (len > 1 && cmp (cp (sp[len] - sp[len - 1], p[i] - sp[len - 1])) < 0)
len--;
sp[++len] = p[i];
}
int k = len;
for (int i = n - 1; i >= 1; i--) {
while (len > k && cmp (cp (sp[len] - sp[len - 1], p[i] - sp[len - 1])) < 0)
len--;
sp[++len] = p[i];
}
return len;
}
int main () {
int t;
cin >> t;
while (t--) {
cin >> n;
char c;
for (int i = 1; i <= n; i++)
cin >> p[i].x >> p[i].y >> c;
int t = Andrew();
cout << t - 1 << endl;
for (int i = 1; i < t; i++)
printf ("%.0lf %.0lf\n", sp[i].x, sp[i].y);
}
return 0;
}
谢谢qaq
【题解】「UVA11626」Convex Hull的更多相关文章
- 【题解】「UVA681」Convex Hull Finding
更改了一下程序的错误. Translation 找出凸包,然后逆时针输出每个点,测试数据中没有相邻的边是共线的.多测. Solution 首先推销一下作者的笔记 由此进入>>> ( ...
- 【题解】「MCOI-02」Convex Hull 凸包
题目戳我 \(\text{Solution:}\) \[\sum_{i=1}^n \sum_{j=1}^n \rho(i)\rho(j)\rho(\gcd(i,j)) \] \[=\sum_{d=1} ...
- P6810 「MCOI-02」Convex Hull 凸包
Link 一句话题意: 求出 \(\displaystyle\sum_{i=1}^{n}\sum_{j=1}^{m}\tau(i)\tau(j)\tau(gcd(i,j))\) 前置知识 \(diri ...
- 题解 「HDU6403」卡片游戏
link Description 桌面上摊开着一些卡牌,这是她平时很爱玩的一个游戏.如今卡牌还在,她却不在我身边.不知不觉,我翻开了卡牌,回忆起了当时一起玩卡牌的那段时间. 每张卡牌的正面与反面都各有 ...
- 题解 「SCOI2016」萌萌哒
link Description 一个长度为 $ n $ 的大数,用 $ S_1S_2S_3 \ldots S_n $表示,其中 $ S_i $ 表示数的第 $ i $ 位,$ S_1 $ 是数的最高 ...
- 题解 「SDOI2017」硬币游戏
题目传送门 Description 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利. 大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实在是太单调了. 同学们觉得要加强 ...
- 题解 「ZJOI2018」历史
题目传送门 Description 九条可怜是一个热爱阅读的女孩子. 这段时间,她看了一本非常有趣的小说,这本小说的架空世界引起了她的兴趣. 这个世界有 \(n\) 个城市,这 \(n\) 个城市被恰 ...
- 题解 「BZOJ3636」教义问答手册
题目传送门 Description 作为泉岭精神的缔造者.信奉者.捍卫者.传承者,Pear决定印制一些教义问答手册,以满足泉岭精神日益增多的信徒.Pear收集了一些有关的诗选.语录,其中部分内容摘录在 ...
- 题解「BZOJ4310」跳蚤
题目传送门 Description 现在有一个长度为 \(n\) 的字符串,将其划分为 \(k\) 段,使得这 \(k\) 段每一段的字典序最大子串中字典序最大的字符串字典序尽量小.求出这个字符串. ...
随机推荐
- brctl 增加桥接网卡
前言 之前有一篇介绍配置桥接网卡的,这个桥接网卡一般是手动做虚拟化的时候会用到,通过修改网卡的配置文件的方式会改变环境的原有的配置,而很多情况,我只是简单的用一下,并且尽量不要把网络搞断了,万一有问题 ...
- android intent-filter 注册网页链接打开app
如下实现注册m.hao123.com的链接: <intent-filter><category android:name="android.intent.category. ...
- property内置装饰器函数和@name.setter、@name.deleter
# property # 内置装饰器函数 只在面向对象中使用 # 装饰后效果:将类的方法伪装成属性 # 被property装饰后的方法,不能带除了self外的任何参数 from math import ...
- 汇编语言CPU状态控制指令
CPU状态控制指令 1.空操作指令NOP /该指令不执行任何操作,只是使IP加1,其机器码占有一个字节的存储单元,常用于程序调试./ 2.总线封锁前缀指令LOCK /该指令与其他指令联合使用,作为指令 ...
- Mysql数据安全备份
数据安全备份的意义 在出现意外的时候(硬盘损坏.断点.黑客攻击),以便数据的恢复 导出生产的数据以便研发人员或者测试人员测试学习 高权限的人员那操作失误导致数据丢失,以便恢复 备份类型 完全备份:对整 ...
- SQL相关子查询是什么?和嵌套子查询有什么区别?
目录 两者的各种叫法 相关子查询MySQL解释 相关子查询Wikipedia解释 相关子查询执行步骤拆解 相关子查询和嵌套查询的区别 参考资料 两者的各种叫法 相关子查询叫做:Correlated S ...
- PHP 递归删除目录中文件
/** * 递归删除目录中文件 * @param $pathname * @return bool */public static function delDir($pathname)//要删除的目录 ...
- Contest 984
A 先手取最大,后手取最小,答案就是第 \(\left\lceil\frac{n}{2}\right\rceil\) 小的数. 用 nth_element 可以做到 \(O\left(n\right) ...
- 【数据结构模版】可持久化线段树 && 主席树
浙江集训Day4,从早8:00懵B到晚21:00,只搞懂了可持久化线段树以及主席树的板子.今天只能记个大概,以后详细完善讲解. 可持久化线段树指的是一种基于线段树的可回溯历史状态的数据结构.我们想要保 ...
- Codeforces Round #670 (Div. 2) D. Three Sequences 题解(差分+思维+构造)
题目链接 题目大意 给你一个长为n的数组a,要你构造一个非严格单调上升的数组b和一个非严格单调下降的数组c,使得\(b_i+c_i=a_i\) 要你使这两个数组b,c中最大的元素最小,还有q次修改(q ...