计算几何 graham 最大凸包

来源:互联网 发布:nothing软件怎么样 编辑:程序博客网 时间:2024/06/06 09:17


http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11326&courseid=117
凸包的严格凸多边形Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:32768KBTotal submit users: 39, Accepted users: 35Problem 11326 : No special judgementProblem description  凸包(convex hull),对于给定集合X,所有包含X的凸集的交集称为X的凸包,记作con(X)。
对于ACMer来说,这么严格复杂的定义可能是没有必要的。我们只要知道平面有限点集的凸包是一个凸多边形就行了。
现在的问题是给定一个平面点集,求出其“严格凸多边形”的凸包。“严格”的意思是凸多边形的边上没有任意三点共线。Input  输入有多个案例。每个案例的第一行是一个整数n,n≤100。随后n行,每一行有2个整数,表示点的x、y坐标,0≤x、y≤2147483647。一个单独的0表示输入结束。没有任何点的坐标是完全一样的。Output  对每一个案例,首先输出一行为其端点的个数,然后按逆时针输出其凸包的顶点的坐标。输出起点是所有顶点的最下最左点(首先是最下,如果有多个点同样处于最下,则取最靠左的)。每个顶点输出一行,中间用空格隔开。Sample Input

30 0100 100100 00
Sample Output
30 0100 0100 100

//严格凸包#include <cstdio>#include <cmath>#include <algorithm>using namespace std;typedef long long llt;#define SIZE 101struct point_t{llt x,y;}P[101];//叉积,OA×OBllt cross(point_t const&O,point_t const&A,point_t const&B){    llt xoa = A.x - O.x;llt yoa = A.y - O.y;llt xob = B.x - O.x;llt yob = B.y - O.y;return xoa * yob - xob * yoa;}//A如果比B更靠下更靠左返回真bool isLowLeft(point_t const&A,point_t const&B){return A.y < B.y || ( A.y == B.y && A.x < B.x );}//按照对于pO的极角排序,极角相等的距离远的排在前面,因为后面要做一个uniquepoint_t* pO;bool comp4Graham(point_t const&A,point_t const&B){    llt t = cross(*pO,A,B);if ( t ) return t > 0LL;llt a1 = A.x > pO->x ? A.x - pO->x : pO->x - A.x;llt a2 = B.x > pO->x ? B.x - pO->x : pO->x - B.x;    if ( a1 != a2 ) return a1 > a2;a1 = A.y > pO->y ? A.y - pO->y : pO->y - A.y;a2 = B.y > pO->y ? B.y - pO->y : pO->y - B.y;return a1 > a2;}//相对于pO是否极角相等bool isEqPolar(point_t const&A,point_t const&B){    return 0LL == cross(*pO,A,B);}//Graham求凸包,结果当中没有共线点,起点总是最下最左点int Graham(point_t P[],int n){    if ( 1 == n ) return 1;//寻找最下最左点point_t *p = min_element(P,P+n,isLowLeft);//交换swap(*p,P[0]);if ( 2 == n ) return 2;//按极角排序,极角相等,距离近的排在前面pO = P;sort(P+1,P+n,comp4Graham);//将相对于pO的共线点均剔除,只保留最后一个p = unique(P+1,P+n,isEqPolar);n = p - P;//真正的Graham循环int top = 2;for(int i=2;i<n;++i){while( top > 1 && cross(P[top-2],P[top-1],P[i]) <= 0LL )--top;P[top++] = P[i];}return top;}int main(){int n;while( scanf("%d",&n) && n ){        for(int i=0;i<n;++i)scanf("%I64d%I64d",&P[i].x,&P[i].y);n = Graham(P,n);printf("%d\n",n);for(int i=0;i<n;++i)printf("%I64d %I64d\n",P[i].x,P[i].y);}return 0;


http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11327&courseid=117

凸包的不严格凸多边形Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:32768KBTotal submit users: 19, Accepted users: 15Problem 11327 : No special judgementProblem description  凸包(convex hull),对于给定集合X,所有包含X的凸集的交集称为X的凸包,记作con(X)。
对于ACMer来说,这么严格复杂的定义可能是没有必要的。我们只要知道平面有限点集的凸包是一个凸多边形就行了。
现在的问题是给定一个平面点集,求出其“不严格”凸多边形的凸包。“不严格”的意思是指将凸包边界上所有的点都看作是多边形的端点。
Input  输入有多个案例。每个案例的第一行是一个整数n,n≤100。随后n行,每一行有2个整数,表示点的x、y坐标,0≤x、y≤2147483647。一个单独的0表示输入结束。
Output  对每一个案例,首先输出一行为多边形端点的个数,然后按逆时针输出其凸包的顶点的坐标。输出起点是所有顶点的最下最左点(首先是最下,如果有多个点同样处于最下,则取最靠左的)。每个顶点输出一行,中间用空格隔开。
Sample Input

40 0100 100100 050 00
Sample Output
40 050 0100 0100 100


严格凸包是在极角排序的时候提前做了处理,所以我们只要把处理取反即可, 代码上只要把极角相等的时候改成近的放前面,去掉unique函数。

typedef long long llt;struct point_t{llt x,y;}P[101];llt cross(point_t const&O,point_t const&A,point_t const&B){    llt xoa = A.x - O.x;llt yoa = A.y - O.y;llt xob = B.x - O.x;llt yob = B.y - O.y;return xoa * yob - xob * yoa;}bool isLowLeft(point_t const&A,point_t const&B){return A.y < B.y || ( A.y == B.y && A.x < B.x );}point_t* pO;bool comp4Graham(point_t const&A,point_t const&B){    llt t = cross(*pO,A,B);if ( t ) return t > 0LL;llt a1 = A.x > pO->x ? A.x - pO->x : pO->x - A.x;llt a2 = B.x > pO->x ? B.x - pO->x : pO->x - B.x;    if ( a1 != a2 ) return a1 < a2; //把这个变成近的放前面a1 = A.y > pO->y ? A.y - pO->y : pO->y - A.y;a2 = B.y > pO->y ? B.y - pO->y : pO->y - B.y;return a1 > a2;}bool isEqPolar(point_t const&A,point_t const&B){    return 0LL == cross(*pO,A,B);}int Graham(int n){    if ( 1 == n ) return 1;point_t *p = min_element(P,P+n,isLowLeft);swap(*p,P[0]);if ( 2 == n ) return 2;pO = P;sort(P+1,P+n,comp4Graham);        //去掉这个//p = unique(P+1,P+n,isEqPolar);//n = p - P;int top = 2;for(int i=2;i<n;++i){while( top > 1 && cross(P[top-2],P[top-1],P[i]) < 0LL )--top;P[top++] = P[i];}return top;}int main(){int n;while( scanf("%d",&n) && n ){        for(int i=0;i<n;++i)scanf("%I64d%I64d",&P[i].x,&P[i].y);n = Graham(n);printf("%d\n",n);for(int i=0;i<n;++i)printf("%I64d %I64d\n",P[i].x,P[i].y);}return 0;}



1 0