POJ1113 计算几何--整形凸包模板周长

今天的主题是凸包!凸包!凸包!


G模板原地址:http://blog.youkuaiyun.com/nyist_tc_lyq/article/details/74776760 

5种凸包的解法思路:http://blog.youkuaiyun.com/bone_ace/article/details/46239187


这题嘛。。4个1/4圆+凸包周长,这城堡比较好,边都能转移出去


记得4舍5入


//求凸包的点
#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
using namespace  std;
const double PI = acos(-1.0);
#define ll long long
#define N 10005
struct point
{
	int x,y;
	point()
	{}
	point(int a,int b)
	{
		x=a,y=b;
	}
	point operator -(const point &b)const
	{
		return point(x - b.x,y - b.y);
	}
	int operator ^(const point &b)const//叉积
	{
		return x*b.y - y*b.x;
	}
	int operator *(const point &b)const	//点积
	{
		return x*b.x + y*b.y;     //绕原点旋转角度B(弧度值),后x,y的变化
	}
} a[N],p[N];//p[]用来储存凸包   a数组存原来的点

struct line
{
	point s,e;
	line() {}
	line(point _s,point _e)
	{
		s = _s;
		e = _e;
	}
} lines[1005];
int xmult(point p0,point p1,point p2) //计算p0p1 X p0p2
{
	return (p1-p0)^(p2-p0);
}

int n,tot;//n为二维平面上点的个数,tot为凸包上点的个数
int dis(point a,point b)
{
	return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
bool cmp(point p1,point p2)//极角排序;
{
	int x=xmult(p1,p2,a[0]);
	if(x>0||(x==0&&dis(p1,a[0])<dis(p2,a[0]))) return 1;
	return 0;
}
bool cmp2(point p1,point p2)
{
	if(p1.x!=p2.x)return p1.x<p2.x;
	return p1.y<p2.y;
}
void Graham()  //O(nlogn)
{
	int k=0;
	for(int i=0; i<n; i++)
		if(a[i].y<a[k].y||(a[i].y==a[k].y&&a[i].x<a[k].x)) k=i;
	swap(a[0],a[k]);//找出左下角最小那个
	sort(a+1,a+n,cmp);
//	for(int i=0; i<n; i++)
//	{
//		cout<<"test:"<<i<<" "<<a[i].x<<" "<<a[i].y<<endl;
//	}
	tot=2,p[0]=a[0],p[1]=a[1];
	for(int i=2; i<n; i++)
	{
		while(tot>1&&xmult(p[tot-1],p[tot-2],a[i])>=0) tot--;
		p[tot++]=a[i];
	}
}
int main()
{
	double R;
	cin>>n>>R;
	for(int i=0; i<n; i++)
	{
		int t1,t2;
		cin>>t1>>t2;
		a[i]=point(t1,t2);
	}
	Graham();
//	sort(p,p+tot,cmp2);
//	for(int i=0; i<tot; i++)
//	{
//		cout<<p[i].x<<" "<<p[i].y<<endl;
//	}
	double ans=PI*R*2.0;
	for(int i=0; i<tot-1; i++)
	{
		ans+=sqrt((double)dis(p[i],p[i+1]));
	}
	ans+=sqrt((double)dis(p[0],p[tot-1]));
	int ans1=(int)(ans+0.5);
	cout<<ans1<<endl;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值