Algorithm Design——凸包
2013-12-01 11:04
411 查看
/** 定义 ⒈ 对于一个集合D,D中任意有限个点的线性组合的全体称为D的凸包。 ⒉ 对于一个集合D,所有包含D的凸集之交称为D的凸包。 可以证明,上述两种定义是等价的 概念 1. 点集Q的凸包(convex hull)是指一个最小凸多边形,满足Q中的点 或者在多边形边上或者在其内。 2. 一组平面上的点,求一个包含所有点的最小的凸多边形,这就是凸包 问题了。这可以形象地想成这样:在地上放置一些不可移动的木桩,用 一根绳子把他们尽量紧地圈起来,并且为凸边形,这就是凸包了。 常用方法: 穷举法,格雷厄姆扫描法,分治法,蛮力法和Jarris步进法 格雷厄姆扫描法思路: (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] = p0,T[k]所构成的三角区负号D,所 D>=0,sp = sp + 1,CHS[sp] = T[k],k = k + 1,转步骤(6);否则,sp = sp - 1,转步骤(6)。 问题描述 某大学 ACM 集训队,不久前向学校申请了一块空地,成为自己的果园。全体队员兴 高采烈的策划方案,种植了大批果树,有梨树、桃树、香蕉……。后来,发现有些坏蛋, 他们暗地里偷摘果园的果子,被 ACM 集训队队员们发现了。因此,大家商量解决办法, 有人提出:修筑一圈篱笆,把果园围起来,但是由于我们的经费有限,必须尽量节省资金, 所以,我们要找出一种最合理的方案。由于每道篱笆,无论长度多少,都是同等价钱。所 以,大家希望设计出来的修筑一圈篱笆的方案所花费的资金最少。有人已经做了准备工作, 统计了果园里所有果树的位置,每棵果树分别用二维坐标来表示,进行定位。现在,他们 要求全体队员,每人给出一个最合理的方案,来解决修筑篱笆所遇到的困难。要求根据所 有的果树的位置,找出一个 n 边形的最小篱笆,使得所有果树都包围在篱笆内部,或者在 篱笆边沿上。 输入: 每行有 2n+1 个整数,第一个为 n,表示果园里面共有n 棵果树,接着2n个数,分别成对 的表示每棵果树pi(xi,yi)的位置,(x1,y1),(x2,y2),...,(xn,yn),3 <= n <= 100,其中, -100 <= xi,yi <= 100 输出: 把设计出来最小 n 边形篱笆的 n 个顶点坐标按逆时针的顺序输出,每个坐标用空格分 开,每个坐标的格式为“(x,y)”。注意,第一个顶点,必须是所有顶点中最低、最左的点。 输入样例: 5 -1 -1 4 3 1 1 0 3 4 0 输出样例: (-1,-1) (4,0) (4,3) (0,3) */ #include <iostream> #include <algorithm> #include <cmath> #include <vector> using namespace std; struct Point { int x; int y; }; Point p[101]; Point min_ld; int n; Point result[101]; //求出两个点的距离 double Distance( const Point &a, const Point &b ) { return sqrt((double)( (a.x - b.x) * (a.x - b.x ) + (a.y - b.y) * (a.y - b.y) ) ); } ///求叉积 int Cross( const Point &s, const Point &p, const Point &q )// sp, sq { Point sp , sq; sp.x = p.x - s.x; sp.y = p.y - s.y; sq.x = q.x - s.x; sq.y = q.y - s.y; return (sp.x * sq.y - sp.y * sq.x); } bool Cmp( const Point &a, const Point &b ) { double d1 = Distance( a, min_ld ); double d2 = Distance( min_ld, b ); if( d1 < 1e-10 || d2 < 1e-10 ) return d1 < d2; double cos1 = ((double)(a.x - min_ld.x))/ d1; double cos2 = ((double)(b.x - min_ld.x))/ d2; if( fabs( cos1 - cos2 ) < 1e-10 ) return d1 < d2; else return cos1 > cos2; } int main() { int k; int top; while( cin >> n ) { for(int i = 0; i < n; i++ ) { cin >> p[i].x >> p[i].y; } k = 0; for(int i = 1; i < n; i++ ) { if( (p[i].y < p[k].y ) || ( p[i].y == p[k].y && p[i].x <p[k].x ) ) { k = i; } } swap( p[0], p[k] ); sort( p + 1, p + n, Cmp ); //cout << '(' << p[0].x << ',' << p[0].y << ')'; //for( i = 1; i < n; i++ ) // cout << ' ' << '(' << p[i].x << ',' << p[i].y << ')'; //cout << endl; result[0] = p[0]; result[1] = p[1]; //result[2] = p[2]; top = 1; for(int i = 2; i < n; i++ ) { while( top > 0 && Cross( result[top], result[top - 1], p[i] ) >= 0 ) --top; result[++top] = p[i]; } cout << '(' << result[0].x << ',' << result[0].y << ')'; for(int i = 1; i <= top; i++ ) cout << ' ' << '(' << result[i].x << ',' << result[i].y << ')'; cout << endl; } return 0; }
相关文章推荐
- Algorithm Design——判断线段是否相交
- Algorithm Design Everyday——2.查找学生信息
- Algorithm Design——查找
- Algorithm Design——高精度整数四则运算
- Algorithm Design——并查集
- Algorithm Design——最小生成树
- Algorithm Design——最短路径
- Algorithm常用函数(3)
- Algorithm常用函数(2)
- Algorithm Design Everyday——1.魔女数字7
- Algorithm常用函数(1)
- 字符串匹配算法之Boyer-Moore-Horspool Algorithm
- 蒙哥马利(Montgomery)算法简介
- Django ModelForm的使用
- Django Form
- Django 自验证
- django如何使ForeignKey字段显示树状结构
- HDU3635Dragon Balls(并查集)
- google probuf反射原理之源码分析
- Rockchip3066 修改开机 LOGO 和开机动画