poj 3301 Texas Trip

 
题目链接:

http://poj.org/problem?id=3301

题目大意:

       给定二维平面的n个点,要求一个面积最小的正方形,使其能覆盖所有的点。

解题思路:

        旋转坐标系,三分法。

       如果正方形两相邻边是与坐标轴平行的,那么只需求出所有点的横坐标差的最大值,纵坐标差的最大值,然后再求两者的最大值,同样的道理当正方形相邻两边与坐标轴不平行时,旋转坐标轴,使新的坐标轴平行正方形的两相邻边,然后把旧坐标轴上的点的坐标全部转化到新的坐标轴上,再求出横纵坐标差的最大值,取两者的最大值即可。分析知二维空间上,对于任意正方形的位置,总能顺时针旋转坐标轴0~90‘ 达到满足要求。

poj 3301 Texas Trip_第1张图片

如图所示当坐标旋转a角度时可以求出 x1=x*cos(a)-y*sin(a);   y1=x*sin(a)+y]*cos(a);  可以证明它们都是凸性函数,故他们差的最大值也是凸性函数,故可以用三分法,对旋转角度进行三分,求出最小的满足要求的正方形,详细过程见代码。

 

#include<iostream>   //g++不能过 c++可以过,精度处理方式不同
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#define eps 1e-12
#define INF (1<<25)
#define PI acos(-1.0)
using namespace std;

double ppx[40],ppy[40];
int n;

double  Cal(double a)
{
    double xMin=INF*1.0,yMin=INF*1.0,xMax=-INF*1.0,yMax=-INF*1.0;

    for(int i=1;i<=n;i++)
    {
        double x1=ppx[i]*cos(a)-ppy[i]*sin(a);
        double y1=ppx[i]*sin(a)+ppy[i]*cos(a);

        if(x1>xMax)
            xMax=x1;
        if(x1<xMin)
            xMin=x1;

        if(y1>yMax)
            yMax=y1;
        if(y1<yMin)
            yMin=y1;
    }
    if(xMax-xMin<yMax-yMin)
        return yMax-yMin;
    else
        return xMax-xMin;

}

int main()
{
    int t;
    int x,y;

    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&x,&y);
            ppx[i]=x+500.0;
            ppy[i]=y+500.0;
        }
        double le=0,ri=PI,mid,mmid;
        double mid_va,mmid_va;

        while(le+eps<=ri)
        {
            mid=(le+ri)/2;
            mmid=(mid+ri)/2;
            mid_va=Cal(mid);
            mmid_va=Cal(mmid);
            if(mid_va<mmid_va)
                ri=mmid;
            else
                le=mid;
        }
        printf("%.2lf\n",Cal(le)*Cal(le));

    }

    return 0;
}


 

 

 

 

你可能感兴趣的:(poj 3301 Texas Trip)