HDU1392 凸包模板

题目大意:求凸包边缘的长度

解题思路:标准的凸包Graham算法

 
  
#include < iostream >
#include
< cmath >
#define PI acos(-1.0)
const double eps = 1e - 6 ;
int sgn( double a) {
return (a > eps) - (a <- eps);
}
struct point{
double x,y;
point (
double xx = 0 , double yy = 0 ){ // 构造函数
x = xx; y = yy;
}
point
operator - (point b){
return point(x - b.x,y - b.y);
}
double operator * (point b){
return (x * b.y - y * b.x);
}
double len(){
return sqrt(x * x + y * y);
}
void input(){
scanf(
" %lf%lf " , & x, & y);
}
}p[
102 ];
int stack[ 102 ],top;
int cmp( const void * a, const void * b) // 逆时针排序 返回正数要交换
{
struct point * c = ( struct point * )a;
struct point * d = ( struct point * )b;
double k = ( * c - p[ 0 ]) * ( * d - p[ 0 ]);
if (sgn(k) < 0 ) return 1 ;
else if (sgn(k) == 0 && sgn(( * c - p[ 0 ]).len() - ( * d - p[ 0 ]).len()) >= 0 )
return 1 ;
else return - 1 ;
}

void graham( int n) // 形成凸包
{
int i;
for (i = 0 ;i <= 2 ;i ++ )
stack[i]
= i;
top
= 2 ;
for (i = 3 ;i < n;i ++ )
{
while ( sgn((p[i] - p[stack[top - 1 ]]) * (p[stack[top]] - p[stack[top - 1 ]])) > 0 ){
top
-- ;
if (top == 0 ) break ;
}
top
++ ;
stack[top]
= i;
}
}

int main()
{
int n,i;
double sum;
while (scanf( " %d " , & n),n)
{
for (i = 0 ;i < n;i ++ )
p[i].input();
if (n == 1 ){
printf(
" 0.00\n " );
continue ;
}
if (n == 2 ){
printf(
" %.2lf\n " ,(p[ 0 ] - p[ 1 ]).len());
continue ;
}
int u = 0 ;
for (i = 1 ;i < n;i ++ ) // 找左下角的点
if (p[i].y < p[u].y || (p[i].y == p[u].y && p[i].x < p[u].x) )
u
= i;
// swap
point tmp = p[ 0 ];
p[
0 ] = p[u];
p[u]
= tmp;
qsort(p
+ 1 ,n - 1 , sizeof (p[ 0 ]),cmp);

graham(n);

sum
= 0 ;
for (i = 0 ;i <= top;i ++ )
sum
+= (p[stack[i]] - p[stack[(i + 1 ) % (top + 1 )]]).len();
printf(
" %.2lf\n " ,sum);
}
return 0 ;
}

PS;这题和ZJU1453、FOJ1333一样,但ZJU和FOJ上n==2时输出2*(p[0]-p[1]).len()。

转载于:https://www.cnblogs.com/DreamUp/archive/2010/08/29/1811829.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值