TOJ 1255


题目标题:

Surround the Tree


题目连接:

http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1255


题目类型:

计算几何 - 凸包


数据结构:

struct LMIC_PNT
{
	int x, y;
	
	bool operator < ( const LMIC_PNT & K ) const
	{
		return y < K.y || y == K.y && x < K.x;
	}
} ;


思路分析:


这里单纯的采用 jarvis 的步进法

这里值得注意的是

题目中所求的是凸包的最外围的长度

而不是现实中所理解的要把外面的点"围"起来

所以2个点的话

应该是两个点的距离 而不是一个来回


证明:


源代码:

#include <iostream>
#include <stdio.h>
#include <math.h>

using namespace std;

#define MAXN 1005
#define PI acos( -1 )

struct LMIC_PNT
{
	int x, y;
	
	bool operator < ( const LMIC_PNT & K ) const
	{
		return y < K.y || y == K.y && x < K.x;
	}
} ;

int n, cnt, tail, arr[MAXN], sta[MAXN];
LMIC_PNT pnt[MAXN];

bool _crolft( LMIC_PNT p1, LMIC_PNT p2, LMIC_PNT p3 )
{
	return ( ( p3.x - p1.x ) * ( p2.y - p1.y ) - ( p2.x - p1.x ) * ( p3.y - p1.y ) ) < 0;
}

void _jarvis()
{
	int i;
	
	tail = cnt = 0;
	
	sort( pnt, pnt + n );
	
	sta[tail ++] = 0;
	sta[tail ++] = 1;
	
	for( i = 2; i < n; i ++ )
	{
		while( tail > 1 && !_crolft( pnt[sta[tail - 1]], pnt[sta[tail - 2]], pnt[i] ) )
		{
			tail --;
		}
		
		sta[tail ++] = i;
	}
	
	for( i = 0; i < tail; i ++ )
	{
		arr[cnt ++] = sta[i];
	}
	
	tail = 0;
	sta[tail ++] = n - 1;
	sta[tail ++] = n - 2;
	
	for( i = n - 3; i >= 0; i -- )
	{
		while( tail > 1 && !_crolft( pnt[sta[tail - 1]], pnt[sta[tail - 2]], pnt[i] ) )
		{
			tail --;
		}
		
		sta[tail ++] = i;
	}
	
	for( i = 0; i < tail; i ++ )
	{
		arr[cnt ++] = sta[i];
	}
}

int main()
{
	int i, c = 1;
	
	while( scanf( "%d", &n ), n )
	{
		for( i = 0; i < n; i ++ )
		{
			scanf( "%d%d", &pnt[i].x, &pnt[i].y );
		}
		
		if( n == 1 )
		{
			printf( "0.00\n" );
			continue;
		}
		
		_jarvis();
		
		double r = 0.0;
		
		for( i = 0; i < cnt - 1; i ++ )
		{
			int tmp_x = ( pnt[arr[i]].x - pnt[arr[i + 1]].x ),
			tmp_y = ( pnt[arr[i]].y - pnt[arr[i + 1]].y );
				
			r += sqrt( tmp_x * tmp_x + tmp_y * tmp_y * 1.0 );
		}
		
		if( n == 2 )
		{
			printf( "%.2lf\n", r / 2 );
		}
		else
		{
			printf( "%.2lf\n", r );
		}
	}
	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值