水平序的Graham-Scan算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
typedef double Type; // 注意下面的fabs()
const int maxn = 1005;
const double EPS = 1e-8;
const double Pi = acos(-1.0);
typedef struct Point {
Type x, y;
Point () {}
Point (Type & xx, Type & yy) : x(xx), y(yy) {}
}Point;
// 判断正负.
int dblcmp(Type d) {
if (fabs(d) < EPS) return 0; // 注意数据类型不同,abs()也不同.
return d > 0 ? 1 : -1;
}
// 叉乘. cross product of (c->a) and (c->b).
Type Cross(Point & c, Point a, Point b) {
return (a.x - c.x) * (b.y - c.y) - (b.x - c.x) * (a.y - c.y);
}
Type Distance(Point & u, Point & v) {
return sqrt( 0.0 + (u.x - v.x) * (u.x - v.x) + (u.y - v.y) * (u.y - v.y) ); }
int n;
Point point[maxn];
int Stack[maxn];
int top;
double ans;
bool cmp(const Point & a, const Point & b) {
if (a.y == b.y) return a.x < b.x;
return a.y < b.y;
}
void graham_scan() {
int i;
int temp_top;
if (n <= 1) {
top = 0;
return ;
}
sort(point, point + n, cmp); // point[0]即为起点.
// 做右链.
top = -1;
Stack[++top] = 0; Stack[++top] = 1;
for (i = 2; i < n; i++) {
while (top >= 1 && dblcmp(Cross(point[Stack[top - 1]], point[i], point[Stack[top]])) >= 0) top--; // 如果不能左转,则退栈. 如果只要求极点,则共线的点也是不要的(即要加等于).
Stack[++top] = i;
}
temp_top = top; // 此时的栈顶元素一定是第n个点.
// 做左链.
Stack[++top] = n - 2;
for (i = n - 3; i >= 0; i--) {
while (top >= temp_top + 1 && dblcmp(Cross(point[Stack[top - 1]], point[i], point[Stack[top]])) >= 0) top--; // 如果不能左转,则退栈. 如果只要求极点,则共线的点也是不要的(即要加等于).
Stack[++top] = i;
}
// 此时的栈顶元素是第1个点.(如果凸包是一条直线,则左右链倒置相同.)
// 凸包的顶点为point[Stack[0]] 到point[Stack[top - 1]].
}
int main(void) {
int i;
scanf("%d", &n);
for (i = 0; i < n; i++)
{
scanf("%lf %lf", &point[i].x, &point[i].y);
}
graham_scan();
ans = 0;
for (i = 0; i < top; i++) {
printf("%lf %lf\n", point[Stack[i]].x, point[Stack[i]].y);
ans += Distance(point[Stack[i]], point[Stack[i + 1]]); // point[Stack[top]] = point[Stack[0]].
}
printf("%lf\n", ans);
system("PAUSE");
return EXIT_SUCCESS;
}。