凸包问题

凸包问题
 
 
     凸包基础知识见:http://baike.baidu.com/view/707209.htm 或者,
参考《国际大学生程序设计竞赛例题解 》(一)计算几何部分和LRJ的黑书。
研究了两天的凸包问题,也在POJ上找了几道题目练习了一下,这里给出自己写的
Graham扫描法求凸包的模板\源代码:
/*--------------------------------------------------------------------/
/ Abstract: Graham扫描法求凸包                                        /
/ Author:王莉峰(Fandywang)                                            /
/ History:2007-11-21                                                  /
/ Version:Microsoft Visual C++6.0                                     /
/--------------------------------------------------------------------*/
#include 
#include 
#include 

typedef struct CPoint
{
 double x, y;
}Point;
const int MAXSIZE = 10000;
const double EPS = 1E-6;
int  stack[MAXSIZE]; //数组模拟堆栈,存放凸包的逆序顶点
int  top;            //凸包顶点数p[stack[0]...stack[top]]
Point p[MAXSIZE];

void GrahamScan(const int &n); //Graham扫描法求凸包
double Dist(const Point &arg1, const Point &arg2); //两点距离
double Length(const int &n);   //多边形周长
double Area(const int &n);     //多边形面积
void Swap(const int &i, const int &j); //交换两个点
double Multi(const Point &p0, const Point &p1, const Point &p2); //叉积运算
int cmp(const void *arg1, const void *arg2); //自定义排序:按照极角

int main(void)
{
 int  n;
// freopen("Input.txt", "r", stdin);
 while( scanf("%d", &n), n )
 {
  int  i;
  for( i=0; i < n; ++i )
  {
   scanf("%lf %lf", &p[i].x, &p[i].y);
  }
  if( n == 1 )
  {
   printf("周长: 0.00\t面积: 0.00\n");
  }
  else if( n == 2 ) 
  {
   printf("周长: %.2lf\t面积: 0.00\n", Dist(p[0], p[1]));
  }
  else 
  {
    GrahamScan(n); 
   /* for( int k=0; k <= top; ++k )
    {
     printf("%lf  %lf\n", p[stack[k]].x, p[stack[k]].y);
    }*/
    printf("周长: %.2lf\t面积: %.2lf\n", Length(top+1), Area(top+1));
  }
 }

 return 0;
}

double Length(const int &n)
{
 double  sum = Dist( p[stack[n-1]], p[stack[0]] );
 for( int i = 0; i < n-1; ++i )
 {
  sum += Dist( p[stack[i]], p[stack[i+1]] );
 }
 return sum;
}

double Area(const int &n)
{
 double area = 0;
 for( int i=0; i < n-1; ++i )
 {
  area += (p[stack[i]].x*p[stack[i+1]].y) - (p[stack[i+1]].x*p[stack[i]].y);
 }
 area = fabs(area) / 2;
 return area;
}

double Dist(const Point &arg1, const Point &arg2)
{
 return sqrt( (arg1.x - arg2.x)*(arg1.x - arg2.x) + (arg1.y - arg2.y)*(arg1.y - arg2.y) );
}

void Swap(const int &i, const int &j)
{
 Point temp = p[i];
 p[i] = p[j];
 p[j] = temp;
}

//通过矢量叉积求极角关系(p0p1)(p0p2)
//P*Q > 0,P在Q的顺时针方向... ...
double Multi(const Point &p0, const Point &p1, const Point &p2)
{
 return (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);
}

int cmp(const void *arg1, const void *arg2)
{
 Point a = *(Point*)arg1;
 Point b = *(Point*)arg2;

 double k = Multi(p[0], a, b);
 if( k < -EPS ) return 1;
 else if( fabs(k) < EPS && (Dist(a, p[0]) - Dist(b, p[0])) > EPS ) return 1;
 else return -1;
}

void GrahamScan(const int &n)
{
 int  i, u = 0;
 for( i = 1; i < n; ++i )
 {//找到最左下的顶点, 令其为p[0]
  if( ( p[i].y < p[u].y ) || ( p[i].y == p[u].y && p[i].x < p[u].x ) ) u = i;
 }
 i = 0;
 Swap(i, u); //只交换一次

 //将点按照相对p[0]的极角从小到大排序, 用qsort
 qsort( p+1, n-1, sizeof(p[0]), cmp );
 //将每一个点逐一检验, 是凸包点放入栈中, 不是则弹出栈。
 //注意: 排序后, p[0]和p[1]一定是凸包的顶点
 stack[0] = 0; stack[1] = 1; stack[2] = 2;
    top = 2;
 for( int j = 3; j < n; ++j )
 {
  while( Multi( p[j], p[stack[top]], p[stack[top-1]] ) > 0 )
  {
   --top;
   if( top == 0 ) break;
  }
  stack[++top] = j;
 }
}

//凸包题目:
POJ 1113 Wall  凸包的基本应用
POJ 1228 Grandpa's Estate 凸包拓展
POJ 2187 Beauty Contest 用凸包求最远点对
提高题目:
POJ 1794 Castle Walls 
POJ 2007 Scrambled Polygon
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值