现在的位置: 首页 > 综合 > 正文

UVA 10173 Smallest Bounding Rectangle (旋转卡壳最小面积外接矩形)

2013年07月09日 ⁄ 综合 ⁄ 共 1682字 ⁄ 字号 评论关闭

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1114

题意:求给定点集的最小面积外接矩形。

思路:模板(见我博客内)。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define min(x,y) ((x)<(y)?(x):(y))
using namespace std;

struct Point
{
    double x,y;

	void get ()
	{
		scanf("%lf%lf",&x,&y);
    }
}pt[1005],ch[1005];

int n,len;

int DB (double d)
{
	if (fabs(d)<1e-8)
		return 0;
	return d>0?1:-1;
}

double cross (Point p,Point ch,Point x)
{
	return (p.x-x.x)*(ch.y-x.y)-(ch.x-x.x)*(p.y-x.y);
}

int cmp (const void *a,const void *b)
{
	Point aa=*(Point *)a;
	Point bb=*(Point *)b;
	int y=DB(aa.y-bb.y);
	int x=DB(aa.x-bb.x);

	if (y == 0)
		return x==1?1:-1;
	return y;
}

void Graham (Point pt[],Point ch[],int &len,int n)
{
	int i,top=1;
	qsort(pt,n,sizeof(pt[0]),cmp);
    ch[0]=pt[0];
    ch[1]=pt[1];
    for (i=2;i<n;i++)
    {
        while (top>0 && DB(cross(ch[top],pt[i],ch[top-1])) <= 0)
            top--;
        ch[++top]=pt[i];
    }
    int temp=top;
    for (i=n-2;i>=0;i--)
    {
        while (top>temp && DB(cross(ch[top],pt[i],ch[top-1])) <= 0)
            top--;
        ch[++top]=pt[i];
    }
    len=top;
}

double dot(Point a,Point b,Point c)   //求ac在ab边的摄影
{
    return (c.x-a.x)*(b.x-a.x)+(c.y-a.y)*(b.y-a.y);
}

double CalMinRect (Point ch[],int n)
{
    if(n<3) return 0;
    int i,p=1,q=1,r;
    double ans=1e10,a,b,c;
    for(i=0;i<n;i++)
    {
		while (DB(cross(ch[i+1],ch[p+1],ch[i])-cross(ch[i+1],ch[p],ch[i])) == 1)
            p=(p+1)%n;
        while (DB(dot(ch[i],ch[i+1],ch[q+1])-dot(ch[i],ch[i+1],ch[q])) == 1)
            q=(q+1)%n;
        if (i == 0)
			r=q;
        while(DB(dot(ch[i],ch[i+1],ch[r+1])-dot(ch[i],ch[i+1],ch[r])) <= 0)
            r=(r+1)%n;

        a=cross(ch[i],ch[i+1],ch[p]);
        b=dot(ch[i],ch[i+1],ch[q])-dot(ch[i],ch[i+1],ch[r]);
        c=dot(ch[i],ch[i+1],ch[i+1]);
        ans=min(ans,a*b/c);
    }
    return ans;
}

int main ()
{
	while (scanf("%d",&n) && n!=0)
	{
		for (int i=0;i<n;i++)
			pt[i].get();
		if (n<3)
		{
			printf("0.0000\n");
			continue;
		}
		Graham (pt,ch,len,n);
		printf("%.4lf\n",CalMinRect (ch,len));
	}
	return 0;
}

抱歉!评论已关闭.