凸包问题
- 格式:doc
- 大小:129.85 KB
- 文档页数:6
acm数学竞赛试题
ACM数学竞赛试题通常涉及各种数学领域,包括但不限于代数、几何、概率统计和组合数学等。
以下是一些经典的ACM数学竞赛试题:
1. 平面上n个点的k距离和最小值问题:给定平面上n个点,对于每个点,计算它到其他所有点的距离,然后求出这些距离中的k个最小值。
问题是:如何有效地计算这k个最小值?
2.最长公共子序列问题:给定两个序列,找出它们的最长公共子序列。
例如,对于序列
A = [1, 2, 3, 4] 和
B = [2, 3, 4, 5],最长公共子序列是[2, 3, 4]。
3. 凸包问题:给定平面上的一组点,找到一个最小的凸多边形,使得这个多边形能够包含这组点中的所有点。
4. 最短路问题:给定一个有向图,其中每条边都有一个非负的权重,找出图中任意两点之间的最短路径。
5. 子集和问题:给定一个正整数数组和一个目标值,判断数组中是否存在和为目标值的两个非空子集。
例如,给定数组[1, 2, 3, 4] 和目标值7,判断是否存在两个子集,它们的和分别为7。
以上只是ACM数学竞赛试题的一部分,实际上还有更多涉及数学各个领域的题目。
要提高解决这类问题的能力,需要不断练习和研究。
半平面知识点半平面是计算几何学中的一个重要概念,它在很多领域都有广泛的应用。
本文将介绍半平面的基本概念、性质以及如何应用半平面来解决实际问题。
一、半平面的定义半平面是指平面上的一个半边,可以通过一条直线将平面分为两个部分。
在半平面中,直线的一侧被称为半平面的内部,另一侧被称为半平面的外部。
二、半平面的表示方法半平面可以通过不同的表示方法来描述,常见的方法有以下两种: 1. 点法:通过半平面上的一个点和一个法向量来表示。
点表示了半平面的内部,法向量决定了半平面的方向。
2. 边法:通过半平面上的一条边来表示。
边界上的点属于半平面的内部,而边界外的点属于半平面的外部。
三、半平面的性质半平面具有以下几个重要的性质: 1. 半平面的内部是一个无限大的区域,外部是一个有界区域。
2. 半平面内的任意两点可以通过半平面上的直线段相互连接。
3. 两个半平面的交集是一个凸多边形,可以通过多边形的边界来表示。
四、半平面在计算几何中的应用半平面在计算几何中有广泛的应用,下面将介绍两个常见的应用场景。
1.凸包问题凸包是指包含给定点集的最小凸多边形,它在很多计算几何问题中都有重要的作用。
半平面可以用来解决凸包问题,具体步骤如下:(1)先找到点集中的最左下角点P,并将其作为凸包的一个顶点。
(2)按照点P的顺时针方向,依次将剩下的点与已知的边界点进行比较。
(3)如果点Q在半平面内部,则将Q作为新的边界点,否则排除该点。
(4)重复步骤(2)和(3),直到所有的点都被处理完毕。
2.线性规划问题线性规划是一类最优化问题,它在经济学、运筹学等领域具有重要的应用。
半平面可以用来求解线性规划问题,具体步骤如下:(1)将线性规划问题转化为标准形式。
(2)构造半平面的不等式约束。
(3)求解半平面的交集,得到线性规划问题的解。
通过以上两个应用场景的介绍,我们可以看出半平面在计算几何中的重要性。
掌握半平面的定义、表示方法以及应用技巧,可以帮助我们更好地解决实际问题。
二进制搜索算法在计算几何中的应用案例计算几何是数学中的一个重要分支,它研究的是几何图形的性质和计算方法。
在计算几何的研究中,二进制搜索算法是一种常用的方法,它可以高效地解决一些与几何相关的问题。
本文将以几个具体的应用案例来说明二进制搜索算法在计算几何中的重要性和实用性。
案例一:最近点对问题最近点对问题是计算几何中的一个经典问题,它要求在给定的一组点中找出距离最近的两个点。
假设我们有一组n个点的坐标(x, y),我们可以使用二进制搜索算法来解决这个问题。
首先,我们将这组点按照x坐标进行排序,然后使用二分查找算法在x坐标上进行搜索。
对于每个中间点,我们计算它与其相邻点的距离,并记录最小距离。
然后,我们将这组点按照y坐标进行排序,并使用二分查找算法在y坐标上进行搜索。
对于每个中间点,我们计算它与其相邻点的距离,并记录最小距离。
最后,我们比较两次搜索得到的最小距离,取其中较小的一个作为最近点对的距离。
通过使用二进制搜索算法,我们可以在O(nlogn)的时间复杂度内解决最近点对问题,提高了计算效率。
案例二:凸包问题凸包问题是计算几何中的另一个重要问题,它要求找出一个点集中包含所有点的最小凸多边形。
在解决凸包问题时,二进制搜索算法同样发挥了重要作用。
我们可以将凸包问题转化为寻找上凸壳和下凸壳的问题。
首先,我们将点集按照x坐标进行排序,并使用二分查找算法在x坐标上进行搜索。
对于每个中间点,我们将其与其相邻点的斜率进行比较,判断是否在上凸壳上。
然后,我们将点集按照y坐标进行排序,并使用二分查找算法在y坐标上进行搜索。
对于每个中间点,我们将其与其相邻点的斜率进行比较,判断是否在下凸壳上。
最后,我们将上凸壳和下凸壳合并,得到凸包。
通过使用二进制搜索算法,我们可以在O(nlogn)的时间复杂度内解决凸包问题,提高了计算效率。
案例三:线段相交问题线段相交问题是计算几何中的一个常见问题,它要求判断两个线段是否相交。
在解决线段相交问题时,二进制搜索算法同样发挥了重要作用。
凸包的质心计算方法Finding the centroid of a convex hull is a fundamental problem in computational geometry and has important applications in various fields.计算凸包的质心是计算几何学中的基本问题,在各个领域都有重要的应用。
The centroid of a convex hull can be defined as the center of mass of the points that form the convex hull.凸包的质心可以定义为形成凸包的点的质量中心。
There are several methods to calculate the centroid of a convex hull, each with its own advantages and disadvantages. One common method is to use the property of convexity to compute the centroid as a convex combination of the vertices of the convex hull.计算凸包的质心有几种方法,每种方法都有其优点和缺点。
一种常见的方法是利用凸性的性质,将凸包的质心计算为凸包顶点的凸组合。
Another method is the gift wrapping algorithm, which computes the convex hull and then finds the centroid as the average of the vertices.另一种方法是礼物包装算法,该算法计算凸包,然后将凸包顶点的平均值作为质心。
The Quickhull algorithm is also commonly used to calculate the centroid of a convex hull by recursively dividing the set of points and finding the convex hull of each subset.快速计算法也常用于通过递归分割点集并找到每个子集的凸包来计算凸包的质心。
krein milman定理KreinMilman定理KreinMilman定理是数学分析中的一个重要定理,它在凸分析和泛函分析领域扮演着重要的角色。
本文将介绍KreinMilman定理的概念、主要结论以及相关的应用。
1. 引言在凸几何学中,我们经常研究凸集和凸函数。
KreinMilman定理则给出了一个关于凸集的一个重要结论。
2. KreinMilman定理的形式化表述KreinMilman定理是关于紧凸集的性质的一个结果,下面是该定理的形式化表述:定理:设X是一个拓扑矢量空间,K是X中的一个非空紧凸集。
那么K的凸包就是K的闭包。
3. 定理的证明为了证明KreinMilman定理,我们先介绍一些必要的背景知识。
3.1 凸包的概念在凸几何学中,凸包是一个集合的凸组合的运算结果,即包含了集合中所有点的最小凸集。
对于一个给定的集合,它的凸包可以看作是它的所有凸组合的集合。
3.2 极点的性质在紧凸集的研究中,极点是一个重要的概念。
一个集合的极点指的是该集合中不能通过任何凸组合由其他点表示的点。
在证明KreinMilman定理时,我们需要证明K的凸包是等于K的闭包。
为了做到这一点,我们首先证明K的凸包包含于K的闭包。
假设x是K的凸包中的一个点,那么它可以由K中的有限个点的凸组合表示。
由于K是闭的,所以它的闭包也包含了这些点,于是x也属于K的闭包。
接下来,我们证明K的闭包包含于K的凸包。
假设x是K的闭包中的一个点。
我们考虑以x为边界的一个球体,该球体的半径可以任意小。
由于K是紧凸集,所以对于这个球体,我们可以找到一个点y,使得y属于K且距离x最近。
由于y属于K,我们可以通过y来表示x的凸组合,即x属于K的凸包。
综上所述,我们证明了K的凸包等于K的闭包,从而完成了KreinMilman定理的证明。
4. 应用KreinMilman定理在实际问题中有广泛的应用。
它在优化问题、概率论、拓扑学等领域发挥着重要作用。
斯德瓦特定理
斯德瓦特定理是指在多维空间中,任意一个凸包上的点,它到凸包上最近的点距离它的距离总是等于其到凸包的距离。
斯德瓦特定理的证明过程如下:
1.设凸包上的点为$P$,到凸包的距离为$d$,到凸包上最近的点为$Q$,则$PQ$为凸包的边界,且点$P$和点$Q$的连线与凸包在点$P$处的切线平行。
2.设凸包在点$P$处的切线为$l$,则$l$与$PQ$平行,且$l$到$P$的距离为$d$。
3.因为$l$是凸包在点$P$处的切线,所以$l$与凸包的距离为$0$。
4.因此,由三角不等式得到:$PQ≤PL+LQ=d+0=d$
5.又因为$PQ$是凸包的边界,所以$PQ=d$
6.综上所述,得证。
斯德瓦特定理的应用包括:
1.在数学最优化问题中,斯德瓦特定理可以用来求解凸包上的点到凸包的最小距离。
2.在计算机图形学中,斯德瓦特定理可以用来求解物体与平面的最近距离,从而实现深度缓存等功能。
3.在信号处理中,斯德瓦特定理可以用来求解信号与凸包
的最小距离,从而实现信号压缩等功能。
4.在机器学习中,斯德瓦特定理可以用来求解凸集上的点到凸包的最小距离,从而用于支持向量机等算法。
总的来说,斯德瓦特定理是一个重要的数学定理,它在许多领域中都有广泛的应用。
它可以用来求解凸包上的点到凸包的最小距离,并在数学最优化、计算机图形学、信号处理、机器学习等领域中得到广泛应用。
Graham Scan算法一、概述Graham Scan算法是一种用于计算凸包的算法,它可以在给定二维平面上的一组点时,找到这些点形成的凸包。
凸包是包围点集的最小凸多边形,它的边界上的点不弯曲向内。
二、算法原理Graham Scan算法采用了一种基于极角排序的方法来求解凸包,其基本思路如下:1.找到y坐标最小的点P0,将P0作为凸包的起点。
2.将其他点按照与P0的极角进行逆时针排序。
3.遍历排序后的点集,如果凸包的点个数小于2,或者遍历点与前两个点的构成的两条线段的转向(顺时针或逆时针)满足逆时针,则将遍历点添加到凸包中;否则,将凸包的最后一个点移除,再添加遍历点。
4.最终的凸包即为所有添加后剩下的点集。
三、算法实现步骤下面将详细介绍Graham Scan算法的实现步骤:1. 寻找起点先确定凸包的起点,即y坐标最小的点P0。
可以通过比较每个点的y坐标找到最小的那个点。
如果有多个点的y坐标相等,选择其中x坐标最小的点。
2. 极角排序对于起点P0之外的其他点,计算它们与P0的极角,并按照极角进行逆时针排序。
计算极角时,可以使用两点之间的斜率来表示,斜率越大则两点之间的角度越小。
3. 构建凸包从排好序的点集中依次取出每个点Pi,将其添加到凸包中。
首先,检查凸包中的点个数是否小于2。
当凸包中的点个数小于2时,直接将Pi 添加到凸包中。
然后,检查凸包中的最后两个点Pi-1和Pi-2构成的线段的转向。
当这两个点以及Pi构成的三个点满足逆时针时,将Pi添加到凸包中。
反之,将凸包中的最后一个点移除,再将Pi添加到凸包中。
4. 输出凸包最终,凸包中包含了输入点集形成的凸多边形。
遍历凸包中的点,按顺序输出它们的坐标,即可得到凸包。
四、算法复杂度分析时间复杂度1.寻找起点:需要遍历所有点来找到起点,时间复杂度为O(n)。
2.极角排序:对n-1个点进行排序,时间复杂度为O(nlogn)。
3.构建凸包:需要遍历所有点,时间复杂度为O(n)。
三维凸包生成算法解释说明以及概述1. 引言1.1 概述三维凸包生成算法是计算机图形学和计算几何领域的一个重要研究方向。
它涉及到在三维空间中找到能够完全包围给定点集的最小可见表面,这个表面被称为凸包。
三维凸包在计算机图形学、虚拟现实、遥感技术、立体成像等领域都有广泛的应用。
本文将对三维凸包生成算法进行解释说明,并对常见的算法进行概述和比较评估。
首先会介绍凸包的定义和生成问题,然后详细阐述Graham扫描算法、Jarvis 步进算法和QuickHull算法的原理和实现方法。
接下来将对这些算法进行性能评估,并比较它们的优缺点。
最后,我们还将分析三维凸包生成算法在各个应用领域中的具体应用情况,并展望未来发展趋势。
1.2 文章结构本文共分为五个部分:引言、三维凸包生成算法、算法解释与说明、算法概述和评估比较以及结论。
引言部分概述了整篇文章的主题内容以及研究背景,介绍了凸包生成算法在实际应用中的重要性。
接下来的三维凸包生成算法部分将解释凸包的定义和生成问题,并列举常见的算法。
在算法解释与说明部分,详细介绍了Graham扫描算法、Jarvis步进算法和QuickHull算法的原理和流程。
随后,在算法概述和评估比较部分,我们将对这些算法进行性能指标评估,并比较它们的优缺点。
最后,在结论部分,对整篇文章进行总结,并展望未来三维凸包生成算法的发展趋势。
1.3 目的本文旨在提供读者对三维凸包生成算法的全面了解和深入认识。
通过解释说明和概述常见的三维凸包生成算法,读者可以掌握每种算法的原理、实现方法以及其在不同应用领域中的优缺点。
文章还将对这些算法进行评估比较,帮助读者选择适合自己需求的具体实现方法。
同时,本文也希望为未来研究提供一定参考价值,探讨三维凸包生成算法在更广泛领域中可行性和改进方向,促进该领域的发展和创新。
2. 三维凸包生成算法:2.1 凸包定义:凸包是指一个闭集合内的所有点都位于该集合的边界或内部,形成一个多面体。
卡拉泰奥多里定理卡拉泰奥多里定理(Caratheodory's theorem)是数学中的一个重要定理,它关于凸集的性质与表示问题提供了一个关键的结果。
这个定理由希腊数学家康斯坦丁·卡拉泰奥多里(Constantin Caratheodory)于1907年提出,后来又由约翰·冯·诺伊曼(John von Neumann)在20世纪40年代加以推广和证明。
卡拉泰奥多里定理的核心内容是关于凸集的表示问题。
在凸集的研究中,人们常常需要找到一组顶点来表示该凸集,即凸包(convex hull)。
凸包是包含了所有凸集中点的最小凸集。
卡拉泰奥多里定理给出了一种有效的方法来表示凸包。
具体来说,卡拉泰奥多里定理指出,任意一个凸集可以通过包含它的最少数量的凸组合(convex combination)的顶点来表示。
凸组合是指由凸集中的点按照一定的权重进行线性组合得到的点。
因此,卡拉泰奥多里定理实质上给出了凸包的一种等价的表示方式。
卡拉泰奥多里定理的证明并不简单,它需要运用到多个数学分支的知识,包括线性代数、凸分析和测度论等。
该定理的证明可以分为两个关键步骤。
首先,需要证明凸集中的任意一点都可以由凸组合的顶点来表示。
这个步骤可以通过数学归纳法来证明。
假设凸集中的任意k个点都可以由凸组合的顶点来表示,那么可以证明任意k+1个点也可以。
这个证明过程中需要运用到凸性质的性质,例如凸集的定义和凸组合的定义。
其次,需要证明凸集中的点可以由最少数量的凸组合的顶点来表示。
这个步骤是通过反证法来证明的。
假设存在另一种表示方式,其中顶点的数量更少。
然后通过凸性质的性质来推导出一个矛盾的结论,从而证明原来的表示方式是最优的。
卡拉泰奥多里定理的重要性在于它给出了凸包的一种等价的表示方式,为凸集的研究和应用提供了一个重要的工具。
凸集在几何学、最优化问题、经济学和凸分析等领域中都有广泛的应用。
例如,在最优化问题中,凸集常常用来描述约束条件,而凸包的表示可以用来描述可行解集合。
凸包问题摘要:凸包问题是计算机几何中的一个经典问题,它要求将平面内的点集用最少的凸点将所有的顶点封闭。
凸包问题的应用十分广泛,很多最优化问题经过抽象后可以发现它最终是凸包问题模型;它还可以用于人际关系网络的最小化搜索,通过人际关系,可以合理推断出某人的身份,职位等个人特征。
目前求取凸包的常用算法有:穷举法,格雷厄姆扫描法(Graham),分治法,蛮力法和Jarris 步进法。
其中穷举法与蛮力法都是建立在穷举的算法思想上,它们的时间复杂度比较大,格雷厄姆扫描法采用几何方面的知识,降低了求解过程的时间复杂度。
关键词:凸包问题;计算机几何;格雷厄姆扫描法一、引言凸包问题的完整描述:令S 是平面上的一个点集,封闭S 中所有顶点的最小凸多边形,称为S 的凸包,表示为CH(S)。
如下图一所示,由红色线段表示的多边形就是点集Q={p0,p1,...p12}的凸包。
图一凸包问题是计算机几何的一个经典问题,它可以解决很多优化模型,目前目前求取凸包的常用算法有:穷举法,格雷厄姆扫描法(Graham),分治法,蛮力法和Jarris步进法。
本文主要讨论穷举法,蛮力法,以及格雷厄姆扫描法,通过算法思想的描述,计算出相应的时间复杂度,比较这几种算法的优劣。
二、穷举法穷举法的思想很简单直接,它利用凸包性质—如果点集中的两个点的连线属于凸多边形的边,当且仅当点集中其余的点都在这两个点连线的同一侧。
假设点集合S 中有n 个顶点,则这n 个顶点共可以构成(1)2n n -条边,对于任何一条边来讲,检查其余的n-2 个点的相对于该直线段的正负性。
如果它们有相同的正负性,说明该边是凸多边形的边,反之就不属于凸多边形,继续检查。
算法流程图如下:不相同 相同NY图二:算法流程图上述算法(穷举法)需要执行n(n-1)/2 次,再次检查n-2 个点的正负性,故算法时间复杂性为2(1)2n n -∑=3()o n 。
显然这并非一个高效的算法凸包问题有许多更加有效的算法可以达到log n n 的渐近时间复杂度。
三、蛮力法开始从点集S 中取出两个顶 点u ,v 判断其余的n-2 个点的相对于该直线段的正负性 判断执行次数是否大于(1)2n n - 把u ,v 加入凸包结束蛮力法求解凸包问题的基本思想:对于一个由n 个点构成的集合S 中的两个点Pi 和Pj ,当且当该集合中的其他点都位于穿过这两点的直线的同一边时(假定不存在三点同线的情况),他们的连线是该集合凸包边界的一部分。
对每一对顶点都检验一遍后,满足条件的线段构成了该凸包的边界。
检验其余顶点是否同一边时,在平面上,穿过两个点(x1,y1)和(x2,y2)的直线是由下面的方程定义的:ax + by = c (其中a=y2-y1,b=x2-x1,c=x1y2-x2y1)这样一条直线把平面分成两个半平面:其中一个半平面中的点都满足ax + by >c ,另一个半平面中的点都满足ax + by <c ,因此,为了检验这些点是否位于这条直线的同一边, 可以简单地把每个点代入方程ax + by = c ,检验这些表达式的符号是否相同。
此算法的时间复杂度同于穷举法,此算法的巧妙之处在于它对于判断剩余顶点是否在同一边的处理。
由所有不同的点共组成了n(n-1)/2边,要对每条边都要对其他n-2个顶点求出在直线方程ax + by = c 中的符号,所以,其时间复杂性是O(n3)。
代码见附录一四:格雷厄姆扫描算法格雷厄姆扫描法是利用平面上任意3 点所构成的回路是左转还是右转的判别法来求平面点集的凸包。
三角区符号的计算:主要用于判断线段相对于基准线来讲,是位于基准线的左方还是右方。
比如说平面上有3个点p1(x1,y1),p2(x2,y2),p3(x3,y3),让我们判断13p p 是位于12p p 的左方还是右方。
判断方法,用叉积:31,31(31)*(21)(21)*(31)21,21x x y y D x x y y x x y y x x y y --==-------若D>0,则13p p 在12p p 右侧,即在顺时针方向;若D<0, 则13p p 在12p p 左侧,即在逆时针方向;若D=0,则13p p 与12p p 在同一条直线上。
算法第一步:幅角排序。
首先在点集中选取其中y 坐标最小的那个点记为0p ,连接0p 到每个剩余点的线段,将这些线段按逆时针方向进行排序,第一条线段对应的另一顶点标为1p ,后续的线段依次这样标记过程如下图:图三第二步:幅角扫描。
堆栈初始化为CH (S )={pn-1,p0},其中p1 为栈顶元素。
按极坐标的幅角,从p0 开始,到pn-1 为止进行扫描。
假定在某一时刻,堆栈内容为:CH (S )={pn-1,p0,…, pi,pj,pk}其中,pk 为栈顶元素,则栈中元素按顺序构成一个半封闭的凸多边形。
假设l p 是正在扫描的点,如果j k l p p p 构成的路径是左转的,如下图三b 所示,则由k l p p 形成的边将是凸边,可以把作为半封闭的凸多边形中的一条边加入进来,因此把l p 压入栈顶,把扫描线移到下一点;如果j k l p p p 构成的路径是右转的,则k p 不可是凸包的极点,将弹出栈顶,而扫描线仍然停留在l p 上。
如果构成的路径是右转的这样,在下一轮处理中,将由i l j p p p 进行判断和作出处理。
图四3.算法步骤:(1)求平面点集S 中Y 坐标最小的点p0。
(2)以p0 为源点,变换S-{p0}中所有点的坐标(3)以p0 为源点,计算S-{p0}中所有点的幅角。
(4)以幅角的非降排序S-{p0}中所有的点,令事件调度点T={p1,p2,…, pn-1}是排序过的数组。
(5)初始化堆栈:令CHS[0]=pn-1,CHS[1]=p0;令堆栈指针sp=1,事件调度点数组T 的下标k =0。
(6)如果k<n-1,转步骤(7);否则,算法结束。
(7)计算CHS[sp-1],chs[sp]=0p ,T[K]所构成的三角区符号D ,若D 0,则 sp++, CHS[sp]=T[k],k++,转步骤(6);否则,sp--转步骤(6)代码实现见附录二 四、算法比较蛮力法和穷举法都是基于穷举思想的算法,它们的时间复杂度是解决凸包问题算法中最复杂的3()o n ,它们易于理解,适用于解决规模较小的问题。
而格雷厄姆扫描算法的时间复杂度为(log)o n n,它是解决此类问题的一个比较高效的一个算法。
五、学习心得和体会通过此次对凸包问题的研究与学习,我了解到了数学思维对于算法设计的重要性,同时也认识到计算机几何对于问题处理的简化。
用几何知识来解决一些较难的题目,有时会起到意想不到的效果。
用数学方法解决问题永远要比计算机高效,有很多比较难的ACM竞赛题,它考的更多的是数学方法与计算机技术相结合的综合能力,在学好算法的同时,我们更应当学会用数学思维出看待和处理问题。
参考文献:杭电ACM课件-计算机几何讲解刘东英附录:附录一:蛮力法代码Void convex_hull(){int I,j,k,sign=0;double a=0,b=0,c=0;for(i=0;i<MAXNUM;++i)for(j=j+1;j<MAXNUM;++j){a = my_point[j].y – my_point[i].y;b = my_point[j].x – my_point[i].x;c = (my_point[i].x * my_point[j].y) – (my_point[i].y * my_point[j].x)sign=0;for(k=0;k<MAX_NUM;k++){if((k==j)||(k==i))continue;if ((a * my_point[k].x + b*mypoint[k].y)==c)exit(1);if ((a * my_point[k].x + b*mypoint[k].y)>c)++sign;if ((a * my_point[k].x + b*mypoint[k].y)<c)--sign;}if (((sign==(MAX_NUM-2))||((sign==(2- MAX_NUM))){printf("\n\n");my_point[i].flag=1;my_point[j].flag=1;}}printf("\n\n");}附录二:Void convex_hull(POINT S[],POINT CHS[],int n,int &sp{int i,k;float D;SPOINT T[n];for (i=1;i<n;i++) /* s 中Y 坐标最小的点于S[0]*/if ((S[i].y<S[0].y)||((S[i].y=S[0].y)&&S[i].x<S[0].x))swap(S[i],S[0]);for (i=1;i<n;i++) { /*以S[0]为源点,变换S[i]的坐标于T[i-1]*/T[i-1].x=S[i].x-S[0].x;T[i-1].y=S[i].y-S[0].y;T[i-1].ang=atan(T[i-1].y,T[i-1].x); /*求T[i]的幅角*/}Sort(T,n-1); /*按T[i]幅角的非降顺序排序T[i]*/CHS[0].x=T[n-2].x;CHS[0].y=T[n-2].y;CHS[1].x=0;CHS[1].y=0;sp=1;k=0;While (k<n-1) { /*求栈顶两点及扫描线上一点构成的三角符号*/D=CHS[sp-1].x*CHS[sp].y+CHS[sp].x*T[k].y+T[k].x*CHS[sp-1].y-CHS[sp-1].y *CHS[sp].x-CHS[sp].y*T[k].x-T[k].y*CHS[sp-1].x;if (D>=0)CHS[++sp]=T[k+1]; /* 若 ,T[k]压入栈顶,扫描线前移一点*/else sp--; /* 否则,弹出栈顶元素*/}}。