uva10173Smallest Bounding Rectangle (旋转卡壳之最小矩形)

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=13&problem=1114&mosmsg=Submission+received+with+ID+10328241

求卡壳步骤可参考:http://cgm.cs.mcgill.ca/~orm/rotcal.html英文的解说。


最终以点积求长,叉积求宽的方式解决。。。


代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<math.h>
#define eps 1e-8
#define inf 1e10
#define maxn 1020
struct point{double x,y;}points[maxn],p[maxn];
int n;
double xmult(point p1,point p2,point p0)
{
	return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}
bool cmp(const point &a,const point &b)
{
	if(a.y==b.y)return a.x<b.x;
	return a.y<b.y;
}

int Graham()
{
	std::sort(points,points+n,cmp);
	int i;
	p[0]=points[0];
	p[1]=points[1];
	int top=1;
	for(i=2;i<n;i++)
	{
		while(top&&xmult(p[top],points[i],p[top-1])>=0)top--;
		p[++top]=points[i];
	}
	int mid=top;
	for(i=n-2;i>=0;i--)
	{
		while(top>mid&&xmult(p[top],points[i],p[top-1])>=0)top--;
		p[++top]=points[i];
	}
	return top;
}
double min(double a,double b)
{
	return a>b? b: a;
}
double dmult(point p1,point p2,point p0)
{
	return (p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y);
}
double distance(point p1,point p2)
{
	return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
double rc_minarea()//×?D???D????y
{
	if(n<3)return 0;
	int minx=0,maxx=0,miny=0,maxy=0;
	int i;
	p[n]=p[0];p[n+1]=p[1];p[n+2]=p[2];
	for(i=1;i<n;i++)
	{
		if(p[minx].x>p[i].x||p[minx].x==p[i].x&&p[i].y<p[minx].y)minx=i;
		if(p[miny].y>p[i].y||p[miny].y==p[i].y&&p[i].x<p[miny].x)miny=i;
		if(p[maxx].x<p[i].x||p[maxx].x==p[i].x&&p[i].y>p[maxx].y)maxx=i;
		if(p[maxy].y<p[i].y||p[maxy].y==p[i].y&&p[i].x>p[maxy].x)maxy=i;
	}
	int l=minx,r=maxx,t=maxy,b=miny;
	double minn=(p[r].x-p[l].x)*(p[t].y-p[b].y);
	double  dl,dr,dt;
	for(i=0;i<n;i++)
	{
		while(dmult(p[r+1],p[i],p[i+1])-(dl=dmult(p[r],p[i],p[i+1]))>eps)
			r=(r+1)%n;
		while(dmult(p[l+1],p[i+1],p[i])-(dr=dmult(p[l],p[i+1],p[i]))>eps)
			l=(l+1)%n;
		while(xmult(p[t+1],p[i+1],p[i])-(dt=xmult(p[t],p[i+1],p[i]))>eps)
			t=(t+1)%n;
		double dis=distance(p[i],p[i+1]);
		minn=min(minn,dt/dis*(dl/dis+dr/dis-dis));
	}
	return minn;
}
int main()
{
	while(scanf("%d",&n),n)
	{
		int i;
		for(i=0;i<n;i++)
			scanf("%lf%lf",&points[i].x,&points[i].y);
		n=Graham();
		printf("%.4lf\n",rc_minarea());
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值