poj 3301 Texas Trip(旋转+三分)

来源:互联网 发布:html上传到阿里云 编辑:程序博客网 时间:2024/06/06 01:52

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

大意:给出一些点求出最小的正方形面积把它们都覆盖掉。

要解决它我们需要会一些基础知识:坐标旋转公式,三分搜索算法。

逆时针旋转:x=xcosθ+ysinθ;  y=ycosθ-xsinθ
顺时针旋转:x=xcosθ-ysinθ;  y=ycosθ+xsinθ
分析可知,在一个π内可以找到最佳的边长,构造出能够覆盖所有的点同时也是最小的正方形。这涉及到极值问题,所以自然联想到三分搜索算法。
以例子2作为说明对象:

不旋转时正方形的边长是20,当旋转时,可以把坐标系看作和正方形一起旋转,它们的定点是正方形的中心,也是原点。最后找到最小的边长:abs(A.x-D.x)

#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>using namespace std;const int INF=0x3f3f3f3f,pi=3.1415926;typedef struct Point{    int x,y;}point;point p[1005];double cal(double angle,int n){    double minx=INF,maxx=-INF,miny=INF,maxy=-INF;    double tx,ty;    for(int i=0;i<n;i++){        tx=p[i].x*cos(angle)-p[i].y*sin(angle);        ty=p[i].y*cos(angle)+p[i].x*sin(angle);        minx=min(minx,tx);        maxx=max(maxx,tx);        miny=min(miny,ty);        maxy=max(maxy,ty);    }    return max(maxx-minx,maxy-miny);}int main(){    //freopen("cin.txt","r",stdin);    int t;    cin>>t;    while(t--){        int n;        scanf("%d",&n);        for(int i=0;i<n;i++){            scanf("%d%d",&p[i].x,&p[i].y);        }        double l=0,r=pi,mid1,mid2,q1,q2;        while(r-l>1e-9){     //care precision             mid1=l+(r-l)/3;             mid2=r-(r-l)/3;             q1=cal(mid1,n),q2=cal(mid2,n);             if(q1<q2)r=mid2;             else l=mid1;        }        printf("%.2lf\n",cal(l,n)*cal(l,n));    }    return 0;}
注意设置的精度,过小了会WA。

0 0
原创粉丝点击