poj 3301 三分求极值

引用大牛博客内容- -#,勿喷

题目大意:

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

解题思路:

        旋转坐标系,三分法。

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

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

注意:用c++交,g++会出问题;

#include <iostream>
#include <stdio.h>
#include <math.h>
using namespace std;
struct sa
{
    double x,y;
}p[35];
int n;
const double pi=acos(-1.0);
const double eps=1e-6;
double area(double a)
{
    return a*a;
}
double cal(double z)
{
   double x,y;
   double maxx=-1000000,minx=10000000,maxy=-10000000,miny=10000000;
   for(int i=0;i<n;i++)
   {
       x=p[i].x*cos(z)-p[i].y*sin(z);
       y=p[i].x*sin(z)+p[i].y*cos(z);
       if(minx>x) minx=x;
       if(miny>y) miny=y;
       if(maxx<x) maxx=x;
       if(maxy<y) maxy=y;
   }
   return max(area(maxx-minx),area(maxy-miny));
}
double div()
{
   double left=0,right=pi/2.0;
    double ans1,ans2;
    double m,mm;
    do
    {
        m=(left+right)/2.0;
        mm=(right+m)/2.0;
        ans1=cal(m);
        ans2=cal(mm);
        if(ans1<ans2)
            right=mm;
        else
            left=m;
    }while(fabs(ans1-ans2)>eps);
    return ans1;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%lf%lf",&p[i].x,&p[i].y);

        }
        printf("%.2lf\n",div());
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值