凸包算法求凸包点

#include <iostream>
#include <math.h>
#include <algorithm>
using namespace std ;


struct Point
{
int x ;
int y ;
int flag ;  //flag标记该点是否在P0与其他点连线的内部,flag=0表示在内部
}list[500];
int stack[500], top ;


void swap(Point &a, Point &b)
{
Point t ;
t = a ;
a = b ;  
b = t ;
}


int CrossProd(Point p0, Point p1, Point p2)
{
return (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y) ;
}


int compare(const void *pp1, const void *pp2)
{
Point *p1 = (Point*)pp1 ;
Point *p2 = (Point*)pp2 ;
return CrossProd(list[0], *p1, *p2)*(-1) ;
}


void select(int n, int &num)
{
    Point p1, p2 ;
int t, i, j, count  ;
for(i = 1; i < n; ++i)
{
p1 = list[i] ;
if(p1.flag)
{
for(j = i+1; j < n; ++j)
{
p2 = list[j] ;
if(p2.flag)
{
t = CrossProd(list[0], p1, p2) ;  //判断两个点p1, p2是否在同一条直线上
if(t == 0)
{
if((p1.x-list[0].x)*(p1.x-list[0].x) + (p1.y-list[0].y)*(p1.y-list[0].y) < 
(p2.x-list[0].x)*(p2.x-list[0].x) + (p2.y-list[0].y)*(p2.y-list[0].y))
{
list[i].flag = 0 ;
}
 else list[j].flag = 0 ;
}
}
}
}
}
count = 1 ;
for(i = 1; i < n; ++i)
{
if(list[i].flag == 1)
 list[count++] = list[i] ;
}   //剔除掉所有flag为0的点
num = count-1 ;   
qsort(list+1, num, sizeof(Point), compare) ;   //对剩下的点按照对点list[0]的极角从小到大进行快速排序
}


int init(int n)
{
    int i, num ;
for(i = 0; i < n; ++i)
{
cin>>list[i].x>>list[i].y ;
list[i].flag = 1 ;
if((list[i].y < list[0].y) || (list[i].y == list[0].y) && (list[i].x < list[0].x))  //边输入边寻找最低最做端的点
swap(list[0], list[i]) ;
}
select(n, num) ;   //剔除掉所有初步判定为在凸包内部的点,并返回剩余点得数量
return num+1 ;
}


void graham(int n)
{
int i ;
if(n == 1)
cout<<"("<<list[0].x<<","<<list[0].y<<")"<<endl ;
if(n == 2)
cout<<"("<<list[0].x<<","<<list[0].y<<")"<<"("<<list[1].x<<","<<list[1].y<<")"<<endl ;
if(n>2)
{
for(i = 0; i <= 2; ++i)
stack[i] = i ;
top = 2 ;
for(i = 3; i <= n-1; ++i)
{
while(CrossProd(list[stack[top-1]], list[stack[top]], list[i]) <= 0) top-- ;
top++ ;
stack[top] = i ;   //stack[]数组中存储的时list[]数组的下标,利用stack[]数组模拟栈
}
for(i = 0; i <= top; ++i)
cout<<"("<<list[stack[i]].x<<","<<list[stack[i]].y<<")" ;
cout<<endl ;
}
}
int main()
{
int n, num, count = 0 ;
while(cin>>n, n)
{
count++ ;
num = init(n) ;
cout<<"set "<<count<<":\n" ;
graham(num) ;
}
return 0 ;
}


/*
input:
6
1 1
2 2
1 3
2 3
3 1
3 3
0
output:
set 1:
(1,1)(3,1)(3,3)(1,3)
*/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值